归并排序较插入排序要好很多,时间复杂度为 nlogn ,在数据量很大的情况下跟插入排序比起来,那优势就非常明显了。
归并排序的代码如下:
#include <stdio.h> #define MAXSIZE 100 void MergeSort(int a[], int s, int e); //递归分解过程 void Merge(int a[], int s, int m, int e); //实际的归并函数 int main() { int a[MAXSIZE]; int n; printf("Enter N to represent number of digit:"); while(1 == scanf("%d", &n)) { int i; printf("Input %d number(s): ", n); for(i = 0; i < n; ++i) scanf("%d", &a[i]); MergeSort(a, 0, n - 1); printf("After MergeSort: "); for(i = 0; i < n; ++i) printf("%d ", a[i]); printf("\n\nEnter N to represent number of digit:"); } return 0; } void MergeSort(int a[], int s, int e) //递归分解过程 { if(s < e) { int m = (s + e) / 2; MergeSort(a, s, m); MergeSort(a, m + 1, e); Merge(a, s, m, e); } } void Merge(int a[], int s, int m, int e) //实际的归并函数 { int x[MAXSIZE], y[MAXSIZE]; int lena = m - s + 1; int lenb = e - m; x[lena] = 1 << 10; y[lenb] = 1 << 10; int i; for(i = 0; i < lena; ++i) x[i] = a[s + i]; for(i = 0; i < lenb; ++i) y[i] = a[m + 1 + i]; int p, q; p = q = 0; for(i = s; i <= e; ++i) { if(x[p] < y[q]) a[i] = x[p++]; else a[i] = y[q++]; } }运行效果:
将归并排序和插入排序进行比较:
#include <stdio.h> #include <stdlib.h> #include <time.h> #define MAXSIZE 100000 void MergeSort(int a[], int s, int e); //递归分解过程 void Merge(int a[], int s, int m, int e); //实际的归并函数 void insertSortAscending(int array[], int n); //升序插入排序 int main() { int a[MAXSIZE]; int n, i; clock_t start, finish; printf("Enter N to represent number of digit:"); while(1 == scanf("%d", &n)) { //产生n个随机数 srand(time(NULL)); for(i = 0; i < n; ++i) a[i] = rand() % 100000; //归并排序及耗时 start = clock(); MergeSort(a, 0, n - 1); finish = clock(); printf("MergeSort Time used: %lfs\n", (double)(finish - start) / CLOCKS_PER_SEC); //插入排序及耗时 start = clock(); insertSortAscending(a, n); finish = clock(); printf("InsertSort Time used: %lfs\n", (double)(finish - start) / CLOCKS_PER_SEC); printf("\nEnter N to represent number of digit:"); } return 0; } void MergeSort(int a[], int s, int e) //递归分解过程 { if(s < e) { int m = (s + e) / 2; MergeSort(a, s, m); MergeSort(a, m + 1, e); Merge(a, s, m, e); } } void Merge(int a[], int s, int m, int e) //实际的归并函数 { int x[MAXSIZE], y[MAXSIZE]; int lena = m - s + 1; int lenb = e - m; x[lena] = 1 << 10; y[lenb] = 1 << 10; int i; for(i = 0; i < lena; ++i) x[i] = a[s + i]; for(i = 0; i < lenb; ++i) y[i] = a[m + 1 + i]; int p, q; p = q = 0; for(i = s; i <= e; ++i) { if(x[p] < y[q]) a[i] = x[p++]; else a[i] = y[q++]; } } void insertSortAscending(int array[], int n) { int i; for(i = 1; i < n; ++i) { int key = array[i]; int j = i - 1; while(j >= 0 && key < array[j]) { array[j+1] = array[j]; array[j] = key; j--; } } }
比较两种方法的运行效果:
可以看到在数据量为1000的时候归并反而更慢,其原因并不是算法的低效性,而是我写的代码中,每次合并都创建了两个临时数组,分配这些内存需要花较多时间。解决的方法是创建一个大小与待排序数组相同的全局数组来代替。这就不需要再每次合并的时候分配内存了。
当数据量越来越大的时候,可以看到归并排序有明显的优势。
如有错误,请批评指正,谢谢。