算法学习笔记--归并排序

来源:互联网 发布:三六五网络董事长 编辑:程序博客网 时间:2024/05/29 17:26

归并排序:一种简单的利用递归排序的算法,将一个数组先(递归地)将它分成两半分别排序,然后将两半分别排序,然后将结果归并起来。

原地归并的抽象方法:

public static void merge(int[] a, int lo, int mid, int hi){        //将a[lo..mid] 和 a[mid+1..hi] 归并        int N = a.length;        int[] b = new int[N];        int i = lo;        int j = mid + 1;        for (int k = lo; k <= hi; k++) {            b[k] = a[k];        }        //归并回a[lo..hi]        for (int k = lo; k <= hi; k++) {             if(i > mid){                a[k] = b[j++];            }else if(j > hi){                a[k] = b[i++];            } else if(b[i] < b[j]){                a[k] = b[i++];            }else{                a[k] = b[j++];            }        }    }

先将所有元素复制到吧b[]中,然后再归并回a[]中。


归并轨迹如下图:

这里写图片描述
这里写图片描述


自顶向下的归并排序:

这是基于原地归并的抽象实现的递归归并,应用了高效算法设计中的分治思想的典型的例子。

public static void sort(int[] a, int lo, int hi){    // lo,hi 数组下标        if(hi <= lo){            return;        }        int mid = lo + (hi-lo)/2;        sort(a, lo, mid);       //将左半边排序        sort(a, mid+1, hi);    //将右半边排序        Merge.merge(a, lo, mid, hi);  //原地归并的抽象方法    }

要对数组 a[lo..hi] 进行排序,先将它分为a[lo..mid] 和 a[mid+1..hi] 两部分,分别通过递归调用将它们单独排序,最后将有序的子数组归并为最终的排序结果。

归并结果轨迹:

这里写图片描述



自底向上的归并排序:

这种排序的思想是:先归并那些微型数组,然后再成对归并得到的子数组。
先进行两两归并,然后再四四归并,再八八归并。。。

public static void sort(int[] a){        int N = a.length;        for (int sz = 1; sz < N; sz = 2*sz) {     //子数组的大小            for (int lo = 0; lo < N - sz; lo += 2*sz) {   // lo为子数组的索引                Merge.merge(a, lo, lo + sz - 1, Math.min(N - 1, lo + 2*sz -1));            }        }    }


归并轨迹图:

这里写图片描述

特点:

对于长度为N的任意数组,归并排序需要(1/2)N/lgN至NlgN次比较,最多需要访问数组6NlgN次。
可以用归并排序处理数百万甚至更大规模的数组。

0 0
原创粉丝点击