合并排序是用分治策略实现对n 个元素进行排序的算法。其基本思想是,将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成所要求的排好序的集合。
其递归描述如下:
#include <iostream> #define N 8 typedef int Type; using namespace::std; Type *b = new Type[N]; void MergeSort(Type a[], int left, int right); void Merge(Type a[], Type b[], int left, int i, int right ); void MergeSort(Type a[], int left, int right) { if(left < right) { int i = (left + right) / 2; MergeSort(a, left, i); MergeSort(a, i+1, right); Merge(a, b, left, i, right); //Merge to array of 'b' } } void Merge(Type a[], Type b[], int left, int i, int right ) { int x = left, y = i+1, k = left; while((x <= i) && (y <= right)) { if(a[x] < a[y]) b[k++] = a[x++]; else b[k++] = a[y++]; } while(x <= i) b[k++] = a[x++]; while(y <= right) b[k++] = a[y++]; for(int i = left; i < k; i++) a[i] = b[i]; } int main() { Type a[N] = {4,8,3,7,1,5,6,2}; MergeSort(a, 0, 7); for(int i = 0; i < N; i++) cout << a[i] << ','; cout << endl; return 1; }
消去递归的合并算法如下:
#include <iostream> typedef int Type; using namespace::std; void Merge(Type c[], Type d[], int l, int m, int r) { int i = l, j = m+1, k = l; while((i <= m) && (j <= r)) { if(c[i] <= c[j]) d[k++] = c[i++]; else d[k++] = c[j++]; } if(i > m) for(int q = j; q <= r; q++) d[k++] = c[q]; else for(int q = i; q <= m; q++) d[k++] = c[q]; } void MergePass(Type x[], Type y[], int s, int n) { int i = 0; while( i <= n - 2 * s) { Merge(x, y, i, i+s-1, i+2*s-1); i = i+2 * s; } if(i + s < n) Merge(x, y, i, i+s-1, n-1); else for(int j = i; j <= n-1; j++) y[j] = x[j]; } void MergeSort(Type a[], int n) { Type *b = new Type[n]; int s = 1; int i = 0; while(s < n) { MergePass(a,b,s,n); //合并到数组b s += s; MergePass(b,a,s,n); // 合并到数组a s += s; } } int main() { Type num[] = {8,4,7,3,1,5,6,2}; MergeSort(num, 8); for(int j = 0; j < 8; j++) cout << num[j]; int i; cin >> i; return 1; }
自然合并排序如下:
#include <iostream> #define N 8 typedef int Type ; using namespace::std; void MergeSort_Natural(Type a[], int n); int Scan(Type a[], Type b[], int n); void Merge(Type a[], Type b[], int left , int mid, int right); //自然归并排序 void MergeSort_Natural(Type a[], int n) { Type *b = new Type[N]; while(1) { if(Scan(a,b,n) == 0) break; if(Scan(b,a,n) == 0) break; } } /* 线性扫描数列,如果存在逆序的情况就进行合并排序 否则返回一个为零的中间值mid */ int Scan(Type a[], Type b[], int n) { int left = 0, mid = 0, right = n-1; for(int i = 0; i < n-1; i++) { // 判断有没有逆序的情况出现 if(a[i] > a[i+1]){ // 先设置中间值,后设置右值 if(mid == 0) mid = i; else { right = i; Merge(a, b, left , mid, right); left = right+1; mid = 0; right = n-1; } } } // 当最后一个组为最后一个数的极端情况 if((mid !=0) && (right != 0)) Merge(a, b, left , mid, right); return mid; } void Merge(Type a[], Type b[], int left , int mid, int right) { int i = left, j = mid+1, k = left; while((i <= mid) && (j <= right)) { if(a[i] < a[j]) b[k++] = a[i++]; else b[k++] = a[j++]; } while(i <= mid) b[k++] = a[i++]; while(j <= right) b[k++] = a[j++]; } int main() { Type a[N] = {4,8,3,7,1,5,6,2}; MergeSort_Natural(a, 8); for(int i = 0; i < N; i++) cout << a[i] << ','; cout << endl; // int i; // cin >> i; return 1; }
合并排序的一个弊端就是额外需要存储器的空间配置,在实际上的实现上,会极度影响速度和高速缓存的性能!