归并排序 - 递归非递归实现java

瘦欲@ 提交于 2019-12-03 09:33:21

1.归并排序思想:

以2路归并为例,一个有n个记录的序列可以看作n个长度为1的有序子序列,将其两两合并成n/2(向上取整)个长度为2或1的有序序列,当有奇数个记录时为1,重复归并,直到得到一个长度为n的有序序列。

2.归并排序的复杂度:

递归:时间复杂度O(nlongn),空间复杂度O(n+longn)

非递归:时间复杂度O(nlongn),空间复杂度O(n)

所以用到归并排序,还是优先考虑非递归吧。

 3.递归实现

 1     public void mergeSort1(int[] data){
 2         msort(data,0,data.length-1);
 3     }
 4 
 5     public void msort(int[] data, int start, int end){
 6         if(start < end){
 7             int mid = (start + end) >>> 1;
 8             msort(data,start,mid);
 9             msort(data,mid+1,end); //当mid+1 == end时,子序列长度为1,退出msort,进入merge()排序
10             merge(data,start,mid,end);
11         }
12     }
13 
14     public void merge(int[] data, int start, int mid, int end){
15         int s1 = start;     //子序列1在data[]的起始下标
16         int s2 = mid + 1;  //子序列2在data[]的起始下标
17         int[] tmp = new int[end - start +1];
18         int index = 0; //临时数组tmp的下标
19         while((s1 <= mid) && (s2 <= end)){ //两个序列都还没有完全放入tmp[]中
20             if(data[s1] < data[s2]) tmp[index++] = data[s1++];
21             else tmp[index++] = data[s2++];
22         }
23         while(s1 <= mid){ //第2个序列已经完全放入tmp中,由于s1本身是有序的,将s1剩下的元素直接放入
24             tmp[index++] = data[s1++];
25         }
26         while(s2 <= end){
27             tmp[index++] = data[s2++];
28         }
29         for(int i = 0; i < tmp.length; i++){
30             data[start++] = tmp[i];
31         }
32     }

 

4.非递归实现

 1    public void mergeSort2(int[] data){
 2         int k = 1;
 3         while(k < data.length){
 4             merge(data,k);
 5             k *= 2;
 6         }
 7     }
 8 
 9     public void merge(int[] data, int len){
10         int s1 = 0;
11         int e1 = s1+len-1;
12         int s2 = e1+1;
13         int e2 = s2+len-1 < data.length ? s2+len-1 : data.length-1;
14         int[] tmp = new int[data.length];
15         int index = 0;
16         while(s2 < data.length){  //第一种情况存在两个序列
17             while((s1 <= e1) && (s2 <= e2)){
18                 if(data[s1] < data[s2]) tmp[index++] = data[s1++];
19                 else tmp[index++] = data[s2++];
20             }
21             while(s1 <= e1){
22                 tmp[index++] = data[s1++];
23             }
24             while(s2 <= e2){
25                 tmp[index++] = data[s2++];
26             }
27             s1 = e2 + 1;  //处理下一组的两个子序列
28             e1 = s1 + len -1;
29             s2 = e1 + 1;
30             e2 = s2 + len - 1 < data.length ? s2 + len -1 : data.length -1;
31         }
32         while(s1 < data.length){ //第二种情况,只剩下一个子序列了
33             tmp[index++] = data[s1++];
34         }
35         for(int i = 0; i < data.length; i++){
36             data[i] = tmp[i];
37         }
38     }

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!