数据结构系列-归并排序

Posted 一个敲代码的阿信

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构系列-归并排序相关的知识,希望对你有一定的参考价值。

jack原创
第6篇



今日灵光乍现,将之前不懂的归并排序彻底搞清楚了,现在和大家分享。


一 实现过程

将数组对半分成两个数组,一直重复下去直到每个部分只剩下一个元素,将这些元素按照分解的过程重新归并,归并的过程中将元素排好序,直至将所有元素合并



二 分析

递推公式

mergeSort(s,e)=merge(mergeSort(s,r),mergeSort(r,e))  其中r=(s+e)/2

终止条件

s>=e


三 复杂度    

时间复杂度:O(nlogn)

空间复杂度:O(n)

稳定非原地排序


四 注意点

刚开始的时候想要弄懂递推的每个步骤,在每个方法里打印变量,不打印还好,一打印反而更加迷糊了。


初次接触的时候,要观察数据特征,找出递推公式,发现终止条件,要把重点放在递推公式的推导和理解中。


    五 代码


public static void mergeSort(int s, int e,int[] arr,int[] tmp){   
   if(s>=e)return ;    
   int middle = (s+e)/2;    
   //按照递推公式    mergeSort(s,middle,arr,tmp);    mergeSort(middle+1,e,arr,tmp);    merge(s,e,arr,tmp); }

public static void merge(int s,int e,int[]arr, int[] tmp){    
   int start = s;    
   int end = e;    
   int leftMiddle = (s+e)/2;    
   int rightMiddle = leftMiddle+1;    
   int k = 0 ;    
   //这里用的while非常巧妙    while (start <= leftMiddle && rightMiddle <= end){            
       if (arr[start]<arr[rightMiddle])tmp[k++]=arr[start++];            
       else tmp[k++]=arr[rightMiddle++];    }  
   //上一个循环因为start <= leftMiddle 或者 rightMiddle <= end不符合条件而退出,所以需要补充下面两个循环    while (start<= leftMiddle){        tmp[k++] = arr[start++];    }    
   while (rightMiddle <= end){        tmp[k++] = arr[rightMiddle++];    }  
   //将tmp中排好序的元素重新赋值给arr    for (int i = 0;i<k;++i){        arr[s+i] = tmp[i]; //因为tmp和arr的存储维度不同,所以需要s+i    } }


六 测试



七 复杂度分析


时间复杂度为O(nlogn),因为递归的深度为log2n,递归里的每个方法为O(n),所以总的复杂度为O(nlogn)


空间复杂度为O(n),因为归并排序需要额外的tmp的空间,而tmp的长度决定于arr的长度。









以上是关于数据结构系列-归并排序的主要内容,如果未能解决你的问题,请参考以下文章

图解算法系列之归并排序

数据结构系列-归并排序

排序算法系列:归并排序算法

排序算法系列:归并排序算法

算法与数据结构:时间复杂度——以归并排序为例

[ 数据结构 -- 手撕排序算法第六篇 ] 归并排序(下)-- 非递归方法实现