归并排序(一)

上两篇博客介绍了选择排序插入排序希尔排序 这次以我的理解来介绍一下归并排序 在百科上面看到的概念:归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

二路归并就是把2个有序的序列归并到一起,形成一个有序的序列

假如 a =[ 2,4,5,6] b=[1,3,6,9,10]
归并的过程就是先定义一个数组c  c.length = a.length + b.length
int i,j;
i=j=0;  //a,b的索引
for(int k=0;k<c.length;k++){
    if(i>a.length-1)
        c[k]=b[j++]       //当a的元素全部插入到c中是 直接按顺序把b中的元素插入到c中
    else if(j>b.length-1)
        c[k]=a[i++]       //当b的元素全部插入到c中是 直接按顺序把a中的元素插入到c中
    else if(a[i]<b[j])
        c[k]=a[i++]       //a,b中对应值小的插入到c中
    else
        c[k]=b[j++]       //a,b中对应值小的插入到c中
}

归并排序其实是对一个数组采用递归的形式来进行二路归并(下面我们将详细介绍),为了避免额外的开销,我们采用原地归并

下面我们来介绍一下原地归并,由于每次归并我们都要申请而外的空间,来共二个序列来归并,我们想能不能这样,直接定义一个静态数组 每次归并前我们把需要递归的元素复制到这个静态数组里面

下面我们来介绍归并排序的思路;

public static void merge(Comparable [] a,int lo,int mid,int hi){
    int i = lo;
    int j = mid + 1;

    for(int k=lo;k<=hi;k++)
        b[k] = a[k];
    for(int k=lo;k<=hi;k++){
        if(i>mid)
            a[k] = b[j++];
        else if(j>hi)
            a[k] = b[i++];
        else if(less(b[i],b[j]))
            a[k] = b[i++];
        else
            a[k] = b[j++];
    }
}

这是我们原地归并的代码 要注意hi = length-1  mid = lo + (hi-lo)/2

我们先给出归并排序的代码,供读者思考(用递归的思想)

public 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 sort(Comparable [] a){
    b = new Comparable[a.length];
    sort(a,0,a.length-1);
}

下面给出图供大家理解

实际上就是递归到长度为1时返回到上一次 将2个长度为1的归并起来......

全代码:
public class MergeSort {
    public static boolean less(Comparable a,Comparable b){
        return a.compareTo(b)<0;
    }
    private static Comparable [] b;
    public static void merge(Comparable [] a,int lo,int mid,int hi){
        int i = lo;
        int j = mid + 1;

        for(int k=lo;k<=hi;k++)
            b[k] = a[k];
        for(int k=lo;k<=hi;k++){
            if(i>mid)
                a[k] = b[j++];
            else if(j>hi)
                a[k] = b[i++];
            else if(less(b[i],b[j]))
                a[k] = b[i++];
            else
                a[k] = b[j++];
        }
    }

    public static void show(Comparable [] a){
        for(int i=0;i<a.length;i++)
            System.out.printf("%f ",a[i]);
        System.out.println();
    }

    public 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 sort(Comparable [] a){
        b = new Comparable[a.length];
        sort(a,0,a.length-1);
    }
    public static void main(String [] args){
        Double [] test = new Double[10];
        for(int i=0;i<10;i++)
            test[i] = (Math.random()*15);
        show(test);
        sort(test);
        show(test);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_37663299/article/details/81448000