归并排序算法学习笔记

归并排序也是一种分治思想的典型应用,把两个或两个以上的有序表合并成一个有序表,即把待排序序列分成若干子序列,每个子序列是有序的,之后再把有序子序列合并成整体有序序列。

归并排序的平均时间复杂度为O(nlogn),最坏情况为O(nlogn),最优情况为O(n),空间复杂度为O(n),因为排序过程中要用到暂存区,所以该算法比较耗内存,但是效率比较高且是稳定排序。

归并排序的递归版本如下:

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;
       }
}
和快速排序算法一样,归并排序的非递归版本应该也能用栈来模拟实现,以后有时间再实现吧!



posted @ 2014-09-08 16:37  Gright  阅读(221)  评论(0编辑  收藏  举报