归并排序(自底向上操作)

近日学习了归并排序(Merge Sort), 经典的分治思想的运用:将一个大的问题分解成为若干个小问题,通过解决这些小问题从而将整个问题解决。在算法中运用十分普遍。

而归并排序则是将整个数组不断二分,直到将每个数组分成只有一个元素,再通过Merge操作将这些小数组不断归并,成一个大的数组。

归并排序较之其他排序,大大减少的时间复杂度,达到了O(nlogn)。不过,此算法也有着其缺点,那便是空间复杂度随着N的增长线性增加。

  当用归并将一个大数组排序时,我们需要进行很多次归并,因此在每次归并时都创建一个新数组来存储排序结果会带来问题。我们更希望有一种能在原地归并的方法,这样就可以先将前半部分排序,再将后半部分排序,然后在数组中移动元素而不需要使用额外的空间。你可以先停下来想想应该如何实现这一点,乍一看很容易做到,但实际上已有的实现都非常复杂,尤其是和使用额外空间的方法相比。

                                                                          ---------- Algorithm 4th

以下给出merge方法:(merge用于操作已经排序好的数组,由于从一个元素的数组开始,所以在归并过程中所有参与merge的数组已经变成了有序的)

 1 private static void merge(Comparable[] a, int lo, int mid, int hi) {
 2     int i = lo, j = mid + 1;
 3     
 4     for(int k = lo; k <= hi; k++)         //暂存到另一数组中
 5         aux[k] = a[k];
 6     
 7     for(int k = lo; k <= hi; k++) {
 8         if(i > mid)                             //若左数组已全部归并 这放入右数组元素
 9             a[k] = aux[j++];
10         else if(j > hi)                       //若右数组已全部归并 同上
11             a[k] = aux[i++];
12         else if(less(a[j], a[i]))   // 若右数组元素比左数组未并入元素小 放入右数组元素
13             a[k] = aux[j++];
14         else                             
15             a[k] = aux[i++];
16     }
17 }                                            

常规的归并排序是自顶向下,逐步拆分数组,然后进行归并。然而,我们可以换一种思路,直接从小数组开始归并,最终成为一个大的数组。实现如下

sort():

 1 public static void sort(Comparable[] a) {
 2     int N = a.length;
 3     aux = new Comparable[N];
 4     
 5     for(int sz = 1; sz < N; sz = sz + sz) {      //sz为当前子数组长度 由1个开始
 6                                                                         // 每次翻倍
 7         for(int lo = 0; lo < N - sz; lo += sz + sz) {
 8                         //当子数组长度为sz时 对依次对每个子数组进行归并
 9             merge(a, lo, lo + sz - 1, Math.min(lo + sz +sz - 1, N - 1));
10         }
11     }
12     
13 }                                                        

Trace如下:

                                                                            Vane_Tse On the Road.  2014-06-22   22:55:22

                                                                          

                                                                           

原文地址:https://www.cnblogs.com/slimjerk/p/3803212.html