排序-归并排序

归并排序

public class Merge {
    private static Comparable[] aux;
    private Merge(){}
    private static boolean isSorted(Comparable[] a){
        for(int i=1,len=a.length;i<len;i++)
            if(less(a[i],a[i-1])) return false;
        return true;
    }
    private static boolean less(Comparable v,Comparable w){
        return v.compareTo(w)<0;
    }
    private static void show(Comparable[] a){
        for(int i=0,len=a.length;i<len;i++)
            StdOut.print(a[i]+" ");
        StdOut.println();
    }
    private static void merge(Comparable[] a,int lo,int mid,int hi){
        int i = lo,j=mid+1;
        for(int k=lo;k<=hi;k++)
            aux[k] = a[k];
        for(int k=lo;k<=hi;k++)
            if    (i>mid)                a[k] = aux[j++];// 左边完了
            else if(j>hi)                a[k] = aux[i++];// 右边完了
            else if(less(aux[j],aux[i])) a[k] = aux[j++];
            else                         a[k] = aux[i++];
    }
    public static void sort(Comparable[] a){
        int N = a.length;
        aux = new Comparable[N];

        sort(a,0,N-1);
    }
    private static void sort(Comparable[] a,int lo,int hi){
        if(lo>=hi) return;
        int mid = lo + (hi-lo)/2;
        sort(a,lo,mid);// 排序左边
        sort(a,mid+1,hi);// 排序右边
        merge(a,lo,mid,hi);
    }

    public static void main(String[] args){
        String[] a = new In(args[0]).readAllStrings();
        sort(a);
        assert isSorted(a);
        show(a);
    }
}
实现策略

实现归并的方法是将两个不同的有序数组归并到第三个数组中通过创建一个额外的数组,将两个数组中较小的值一个一个的放到新数组中,对大数组进行递归变为一个一个小的数组进行归并排序。归并使用原地归并的方式,不需要每次Merge操作都创建额外的驻足,只需要在排序初始创建一个数组大小的空间,一次性分配aux = new Comparable[N]

分析

假设对16个元素进行排序,会先对左边a[0…7]排序(sort(lo,mid)),然后对a[0…3]进行排序,然后对a[0…1]排序,然后对a[0]和a[1]进行归并操作(merge(a,lo,mid,hi)),然后对a[2]和a[3]进行归并,在对a[0…1]和a[2…3]进行归并,以此类推。在这里插入图片描述
以图中树状图按照成本模型:
已知条件:

  1. 每次merge操作会进行数组长度次比较操作
  2. N个数会形成2n层树->n = lgN

按照成本模型比较次数进行分析,如代码可知。假设具有n层,第k层对应的数组个数有2k个,每个数组的长度是2n-k,固会进行2n-k次比较,每层会进行2n次比较,具有n层,则会进行总共n2n=NlgN次比较

改进

在merge中添加if(less(a[mid],a[mid+1]))当已经有序的情况不在进行归并操作。

自底向上的归并排序

前文列出的排序是自顶向下的归并排序,将大数组变为一个一个小数组进行排序,是算法中分治思想的使用,而自底向上的归并排序更加的自然、循序渐进。按照循环的方法处理。

    // 自底向上的归并排序
    public static void sortFromBottmToTop(Comparable[] a){
        int N = a.length;
        aux = new Comparable[N];
        for(int sz=1;sz<N;sz*=2)// 1个和一个归并 然后两个和两个归并....
            for(int lo=0;lo<N-sz;lo=lo+sz+sz)
                merge(a,lo,lo+sz-1,Math.min(lo+sz+sz-1,N-1));
    }
动态示意图

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值