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

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

原地归并的抽象方法:

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次。
可以用归并排序处理数百万甚至更大规模的数组。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值