歸併排序算法學習筆記

歸併排序也是一種分治思想的典型應用,把兩個或兩個以上的有序表合併成一個有序表,即把待排序序列分紅若干子序列,每一個子序列是有序的,以後再把有序子序列合併成總體有序序列。算法

歸併排序的平均時間複雜度爲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;
       }
}
和快速排序算法同樣,歸併排序的非遞歸版本應該也能用棧來模擬實現,之後有時間再實現吧!
相關文章
相關標籤/搜索