归并排序
本文针对的读者:了解递归,期望加深对归并排序的理解或者第一次接触归并排序
归并排序,前一篇我们讲了插入排序,插入排序之所以叫做插入排序,是因为其复杂度最高的地方在插入的部分,为什么复杂度高?前面一篇已经比较详细的阐述了,因为插入出想的情况有三种,而人脑将三种情况统一在一块代码上,就显得有点困难了。如果是统一在一个概念之下会比较简单。那么这里的归并排序,所谓“归并”,“归”是递归,也就是说这个算法是一个递归的算法,大部分递归的算法都相对来说有容易想的优点,“并”是该算法的核心,也就是说复杂度就在这里了,如何将两个已排好的序列合并成一个排好的序列?这个比较简单,但是在实际编程的时候需要一个小技巧。
下面直接看一下测试代码:
View Code
#include <cstdio> #include <cstdlib> /** * merge a[p..q] and a[q+1..r] */ #define MAX 100 void merge(int a[],int p,int q,int r){ int n1 = q - p + 1; int n2 = r - q; int *L = (int *)calloc(n1+1, sizeof(int)); int *R = (int *)calloc(n2+1, sizeof(int)); //copy data to new space int i, j; for(i=0;i<n1;i++) L[i] = a[p+i]; for(j=0;j<n2;++j) R[j] = a[q+1+j]; //they are flags L[n1] = MAX; R[n2] = MAX; //here is the key process of merge i = j = 0; int k; for(k=p;k<=r;++k){ if(L[i]<=R[j]){ a[k] = L[i]; i++; } else{ a[k] = R[j]; j++; } } free(L); free(R); } void MergeSort(int a[],int p,int r){ if(p<r){ int q = (p+r)/2; MergeSort(a, p, q); MergeSort(a, q+1, r); merge(a, p, q, r); } } int main(){ int a[] = {3, 4, 5, 2, 9 ,1, 7, 6, 8}; int len = sizeof(a)/sizeof(int); MergeSort(a, 0, len - 1); int i; for(i=0;i<len;++i){ printf("%d ", a[i]); } printf("\n"); return 0; }
MergeSort这个函数比较简单,核心在于merge这个函数,merge这个函数里,使用了calloc进行动态内存空间申请,
申请的空间用于存储两个待合并的有序数组,并且在每个数组的末尾放置一个MAX,这里是一个小技巧,构造这样一个
MAX有利于循环继续,写出比较优雅的代码。然后就是不断的取两个数组头中最小的,当取满所有的元素个数即完成任务。
以上论述,有不妥之处,欢迎指正:)