归并排序
归并排序
时间复杂度是 O(nlogn),空间复杂度是O(n);
归并排序算法中,归并最后到底都是相邻元素之间的比较交换,并不会发生相同元素的相对位置发生变化,故是稳定性算法。
C代码:
#include <stdio.h> #include <stdlib.h> void printArray(int a[], int len) { for(int i=0; i<len; ++i) { if(0==i) printf("[%d,",a[i]); else if(i < len-1) printf("%d,",a[i]); else printf("%d]\n",a[i]); } } //将 有序的数组 a、b 合并为一个有序的数组c。数组c要预先分配好内存。 void Merge2(int a[], int left1, int right1, int b[], int left2, int right2, int c[]) { int i = left1, j = left2, k = 0; for(k = 0; i <= right1 && j <= right2; ++k){ if(a[i] <= b[j]) c[k] = a[i++]; else c[k] = b[j++]; } while(i <= right1) c[k++] = a[i++]; while(j <= right2) c[k++] = b[j++]; } //将分别有序的data[s..m] 和 data[m+1 .. n] 归并为有序的 data[s..n] void Merge(int data[], int s, int m, int n){ int i, start = s, k=0; int *temp = (int*) malloc((n-s+1)*sizeof(int)); for(i=m+1; s<=m && i<=n; ++k){ if( data[s] <= data[i] ) temp[k]=data[s++]; else temp[k] = data[i++]; } for(; s<=m; ++k) temp[k] = data[s++]; for(; i<=n; ++k) temp[k] = data[i++]; //拷贝 temp 到 data里 for(i=0; i<k; ++i){ data[start++] = temp[i]; } free(temp); } void MSort(int data[], int left, int right){ if(left < right){ int mid = left + (right-left)/2; MSort(data, left, mid); MSort(data, mid+1, right); Merge(data, left, mid, right); } } int min(int x, int y) { return x < y ? x : y; } //归并排序(C-迭代版) void MSort2(int data[], int left, int right) { int seg, len = right-left+1, start; for(seg = 1; seg < len; seg += seg) { for (start = 0; start < len; start += seg + seg) { int low = start, mid = min(start+seg,len), high = min(start+seg+seg,len); Merge(data,low,mid-1,high-1); } } } int main(){ //int a[] = {4,10,55,5,22,32,72,113}; //int len = sizeof(a)/sizeof(a[0]); //int m = 2; //printArray(a,len); //Merge(a,0,m,len-1); //printArray(a,len); // int a[] = {1,2,3,4,9,15,16,21,45}; // int b[] = {3,5,6,7,11,17,18,200}; // int aLen = sizeof(a)/sizeof(a[0]); // int bLen = sizeof(b)/sizeof(b[0]); // int len = aLen+bLen; // int *res = (int*) malloc(len*sizeof(int)); // Merge2(a,0,aLen-1,b,0,bLen-1, res); // printArray(res,len); // free(res); // int a[] = {4,10,55,5,22,32,72,113,200}; // int len = sizeof(a)/sizeof(a[0]); // int m = 2; // printArray(a,len); // int res[100] = {0}; // Merge2(a,0,m,a,m+1,len-1,res); // printArray(res,len); int a[]={3,7,9,2,1,0,15,10,12}; int len = sizeof(a)/sizeof(a[0]); printArray(a,len); MSort2(a,0,len-1); printArray(a,len); return 0; }
C++:
//自己写的 void Merge(int* a, int n, int* b, int m) { int *ret = new int[n+m]; int i = 0, j = 0, k = 0; while(i<n && j<m) { if(a[i]<=b[j]) ret[k++] = a[i++]; else ret[k++] = b[j++]; } while(i<n) ret[k++] = a[i++]; while(j<m) ret[k++] = b[j++]; for(int ii = 0; ii<n+m; ++ii)//把结果复制给原数组(要足够大) a[ii] = ret[ii]; delete [] ret; } //二路归并,先长度为1的两个子序列排序,然后2,4,8...的两个子序列归并排序。 void MergeSort(int a[], int n) { for(int len = 1; len < n; len *= 2) { int i=0; for(i=0; (i+2*len-1) < n; i=i+2*len) { Merge(a+i,len,a+i+len,len); } if(i+len-1 < n-1)//剩余两个子文件,但有一个的长度小于length { Merge(a+i,len,a+i+len,n-i-len); } } }
--
常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。
昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。