歸併排序也是一種分治思想的典型應用,把兩個或兩個以上的有序表合併成一個有序表,即把待排序序列分紅若干子序列,每一個子序列是有序的,以後再把有序子序列合併成總體有序序列。算法
歸併排序的平均時間複雜度爲O(nlogn),最壞狀況爲O(nlogn),最優狀況爲O(n),空間複雜度爲O(n),由於排序過程當中要用到暫存區,因此該算法比較耗內存,可是效率比較高且是穩定排序。code
歸併排序的遞歸版本以下:blog
void Merge(int a[], int first, int mid, int last, int temp[]){ int i, j, k; i = first; j = mid + 1; k = first; while(i <= mid && j <= last){ if(a[i] < a[j]) temp[k++] = a[i++]; else temp[k++] = a[j++]; } while(i <= mid) temp[k++] = a[i++]; while(j <= last) temp[k++] = a[j++]; i = k = first; while(i <= last && k <= last){ // 把排好序的暫存區回寫到原序列中 a[i++] = temp[k++]; } }
void mergesort(int a[], int first, int last, int temp[]){ if(first < last){ int mid = (first + last)/2; mergesort(a, first, mid, temp); mergesort(a, mid + 1, last, temp); Merge(a,first, mid, last, temp); } }歸併排序非遞歸版本以下:
void mergesortNonRecursion(int a[], int n, int temp[]){ int size = 1, low, mid, high; while(size <= n-1){ // 遞歸版實際上是把序列每次1/2的往下分解,非遞歸就是這個過程逆過來,用兩個循環,外循環加倍步長size,內循環用size分割子序列,分段合併子序列 low = 0; while(low + size <= n-1){ mid = low + size-1; high = mid + size; if(high > n - 1) high = n - 1; Merge(a, low, mid, high, temp); printf("low:%d mid:%d high:%d ", low, mid, high); low = high + 1; } size *= 2; } }和快速排序算法同樣,歸併排序的非遞歸版本應該也能用棧來模擬實現,之後有時間再實現吧!