经典算法系列二-归并排序
今天来谈谈排序效率较高的归并排序算法。
思想:
分治 + 合并
具体点说就是将一个数组分成左右两个部分,然后将左右两个部分的顺序排好后,在合并到一起!
那么怎么将左右两个部分的顺序排好呢?
我们这样看,用递归的思想,将左右两个部分再次分成各个的两个部分,直到每个部分的数据个数为1。这样我们便得到了有序的部分数组。
接着,我们将这些数组合并。最终便会成为有序的数组。
看代码:
1 /* 2 *归并排序 3 *丁洋 4 */ 5 #include<stdio.h> 6 #include<stdlib.h> 7 #include<malloc.h> 8 #include<time.h> 9 /* 10 *合并数组 11 *a[first --- mid-1] 12 *a[mid+1 --- last] 13 */ 14 void mergearray(int a[], int first, int mid, int last, int temp[]) 15 { 16 int i = first; 17 int j = mid + 1; 18 int n = last; 19 int m = mid; 20 int k=0; 21 while(i <= m && j <= n){ 22 if(a[i] <= a[j]){ 23 temp[k++] = a[i++]; 24 } 25 else{ 26 temp[k++] = a[j++]; 27 } 28 } 29 while(j <= n){/*右边还有数据*/ 30 temp[k++] = a[j++]; 31 } 32 33 while(i <= m){/*左边还有数据*/ 34 temp[k++] = a[i++]; 35 } 36 for(i=0;i<k;i++)/*注意此处的写法,从first开始*/ 37 a[first + i] = temp[i];/*合并排序后的数组*/ 38 } 39 /* 40 *将数组分为A,B两个部分 ,分治思想 41 */ 42 void merge_sort(int a[],int left,int right,int temp[]) 43 { 44 if(left < right) 45 { 46 int mid = (left + right) / 2; 47 merge_sort(a,left,mid,temp); /*A区有序*/ 48 merge_sort(a,mid + 1,right,temp); /*B区有序*/ 49 mergearray(a,left,mid,right,temp); /*合并AB区*/ 50 } 51 } 52 53 void sort(int a[],int n)/*使用一个临时指针*/ 54 { 55 int *p; 56 p = (int *)malloc(sizeof(int) * n); 57 merge_sort(a,0,n-1,p); 58 free(p); 59 } 60 61 int main() 62 { 63 int i; 64 int a[4] = {3,1,6,2}; 65 clock_t start, finish; 66 double duration; 67 /* 测量一个事件持续的时间*/ 68 start = clock(); 69 sort(a,4); 70 for(i=0;i<4;i++) 71 printf("%d ",a[i]); 72 // sleep(500); 73 finish = clock(); 74 duration = (double)(finish - start) / CLOCKS_PER_SEC; 75 printf( "\n%f seconds\n", duration ); 76 system("pause"); 77 }
测试结果时间显示为0,郁闷了,然后谷歌了一下,发现这是我时间精度的问题,在c语言中,最小也只能到毫秒级别的了。所以加上一个,sleep(500),呵呵,结果出来了,
在很多的时间复杂度为O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序),
归并排序效率还是较高的。
下一节谈谈堆排序吧!