Merge sort
今天学习merge sort
这个排序算法的思想就是,不停的将数组二分,再将两个子数组不停归并。其中有一个操作叫merge如下图所示。左右两边两个部分是有序的,然后思想也很简单 有两个指针i和j,i指向lo,j指向mid+1,然后比较两个指针所指的大小,如果小就选出来排到数组中,如果i大于mid了 直接将j指针所指内容一直放入数组,反之亦然。
下面是merge操作的java implementation
1 public class MergeSort{ 2 3 private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi){ // 把item复制到aux数组里面 4 for(int i = lo;i <= hi,i++) aux[i] = a[i]; 5 6 int i = lo, j = mid+1; 7 for(int k = lo;k <= hi;k++){ 8 9 if(i > mid) a[k] = aux[j++]; 10 else if (j > hi) a[k] = aux[i++]; 11 else if (less(a[i], a[j])) a[k] = a[i++]; 12 else a[k] = a[j++]; 13 14 } 15 16 17 } 18 19 }
这段代码应该很好理解
下面是merge sort的完整java implementation
1 public class MergeSort{ 2 private static void merge(...){// as before} 3 private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi){ 4 5 if(hi <= lo) return; 6 int mid = lo + (hi - lo)/2; 7 sort(a, aux, lo, mid); 8 sort(a, aux, mid+1, hi); 9 merge(a,aux,lo, mid, hi); 10 } 11 public static void sort(Comparable[] a){ 12 Comparable[] aux = new Comparable[a.length]; 13 sort(a, aux, 0, a.length - 1); 14 15 16 } 17 18 }
值得一提的是 merge sort 对于大小为N的数组,排序用的比较次数最多为N lg N,访问次数最多为 6 N lg N。
下面是一个简短的证明
这里我们假设N是2的幂次方
两边同时乘以N就可以得到前面的命题了。比较次数和访问次数的证明类似。
Merge Sort在时间复杂度上是最优的算法,但是缺点是他需要用额外的空间来保存数组的元素也就是aux数组。
此外再引入 sort stability的概念
就是当我们已经用一个排序算法比如selection sort对item 的某个key排序以后,然后再用另外一个算法,比如 insertion sort,如果说第二次里面相同的key的item 再第二次排序以后他们第一次的key相对位置任然有序,就说第二种算法是稳定的。
不稳定的算法:shell sort,selection sort
稳定的:insertion sort, merge sort