归并排序

来源:互联网 发布:笔记本电脑降温软件 编辑:程序博客网 时间:2024/06/07 09:38

归并排序

  归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用,它包含归(递归)并(合并)两个操作。


原理

  先思考怎么把两个有序的序列A,B组合成一个新的有序序列C。
1. 取两个序列A,B的第一个元素a1,b1做比较,将较小元素放入序列C中并从原来的序列中移除,假设 a1<b1 ,我们把a1放入C中并从序列A中移除它。
2. 这样序列A中的第一个元素变为a2,序列B中第一个元素还是b1,重复第1步直到A,B中某个序列的所有元素全被移除。
3. 将A,B中还存在元素的序列中的元素,按顺序添加到序列C的后面,这样就完成了两个有序序列的合并。

  现在我们有一个乱序数组A,想把其中的元素排序,我们可以考虑把A从中值处分隔成两个数组B和C,对B和C分别排序之后,将他们合并成一个用上面的方法合并成一个新的有序数组。
  我们发现,如果数组只有一个元素的话,那它肯定是一个有序数组,所以我们可以对B和C再进行拆分,对拆分出来的数组继续拆分直到所有的子数组都只有一个元素为止,这样所有的子数组都是有序的,对它们两两进行合并,最后终将可以合并成一个有序的数组。

示例

  • 假设有数组 
    {3,5,4,2,1}
  • 第一次拆分 
    {3,5,4} {2,1}
  • 再一次拆分 
    {3,5} {4} {2} {1}
  • 再一次拆分 
    {3} {5} {4} {2} {1}
  • 合并   
    {3} {5}{3,5}
  • 合并   
    {3,5} {4}{3,4,5}
  • 合并   
    {2} {1}{1,2}
  • 合并   
    {3,4,5} {1,2}{1,2,3,4,5}

代码

//合并有序数组void mergeArray(int* arr, int left, int mid, int right, int* temp){    int i = left, j = mid + 1;    int k = 0;    while(i <= mid && j <= right) {        if(arr[i] < arr[j]) {            temp[k++] = arr[i++];        } else {            temp[k++] = arr[j++];        }    }    while(i <= mid) {        temp[k++] = arr[i++];    }    while(j <= right) {        temp[k++] = arr[j++];    }    for(int p = 0; p < k; p++) {        arr[left + p] = temp[p];    }}
//递归拆分数组为元素只有1个的有序数组void mergeSort(int* arr, int left, int right, int* temp){    if(left < right) {        int mid = (left + right) / 2;        mergeSort(arr, left, mid, temp);        mergeSort(arr, mid + 1, right, temp);        mergeArray(arr, left, mid, right, temp);    }}void mergeSort(int* arr, int len){    int* temp = (int*)malloc(sizeof(int) * len);    mergeSort(arr, 0, len - 1, temp);}

时间复杂度

归并排序的时间复杂度为O(nlogn)

原创粉丝点击