自顶向下与自底向上的归并排序

自顶向下的归并排序

在本节中我们所讨论的算法都基于归并排序这个简单的操作,即将两个有序的数组归并排序成一个有序数组.很快人们就根据这个操作发明了一种简单的归并算法.要将一个数组排序,可以先将它分成两半分别排序,然后将结果归并起来.你将会看到,归并排序吸引人的性质是它能够保证将任意长度为N的数组排序所用的时间和NlogN成正比,它的主要缺点是所利用的额外空间和N成正比.

代码格式如下:

public class Merge {
    private static int[] aux;
​
    public static void main(String[] args) {
        int[] A = { 2, 4, 1, 23, 54, 12, 65, 121, 45, 12, 44 };
        aux = new int[A.length];
        sort(A, 0,A.length-1);
        show(A);
    }
​
    public static void sort(int[] A, int lo, int hi) {
        //将数组A[lo...hi]排序
        if (hi <= lo)
            return;
        int mid = lo + (hi - lo) / 2;
        sort(A, lo, mid);
        sort(A, mid + 1, hi);//思想
        merge(A, lo, mid, hi);
    }
​
    public static void merge(int[] 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 (aux[j] < aux[i])
                A[k] = aux[j++];
            else
                A[k] = aux[i++];
​
        }
    }
​
    public static void show(int[] A) {
        for(int i=0; i<A.length; i++)
        {
            System.out.print(A[i]+"  ");
        }
    }
}

自顶向下的归并排序,先将它们细分到很小的部分,然后层层回溯,单独排序然后将有序的子数组归并成有序的数组.

要理解该排序就需要单独理解它的动态情况.

自底向上的归并排序

import java.lang.Math;
public class MergeBu {
    private static int[]aux;
    public static void main(String[] args) {
        int[] A = { 21, 34, 24, 43, 654, 0, 67, 2, 5, 2, 4, 423, 5, 36, 45, 62, 435, 4634, 524, 324, 5434212, 1 };
        aux = new int[A.length];
        for (int sz = 1; sz < A.length; sz *= 2) {//子数组大小1,2,4,8...
            for (int lo = 0; lo+sz < A.length; lo += 2 * sz) {
                merge(A, lo, lo + sz - 1, Math.min(lo + 2 * sz - 1, A.length - 1));
            }
        }
        show(A);
​
    }
public static void show(int []A){
    for (int i = 0; i < A.length; i++) {
        System.out.print(A[i]+" ");
    }
}
    public static void merge(int[] A, int lo, int mid, int hi) {
        int m=lo,n=mid+1;
        for (int i = lo; i <= hi; i++) {
            aux[i] = A[i];
        }
        for (int i = lo; i <=hi; i++) {
            if (m > mid)
                A[i] = aux[n++];
            else if (n > hi)
                A[i] = aux[m++];
            else if (aux[m] > aux[n])
                A[i] = aux[n++];
            else
                A[i] = aux[m++]; 
        }
    }
}

自底向上的归并排序会多次遍历整个数组,根据子数组的大小进行两两归并,子数组的大小sz的初始值为1,每次加倍,最后一个子数组的大小只有在数组大小是sz的偶数倍的时候才会等于sz(否则会比sz小).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值