归并排序

归并排序

小弟初来咋到,面对算法一脸懵逼,希望各位大神能够给予指点,在此谢过。

自上而下的归并排序

思路:化整为零,将一个大的序列分成两半分别排序,最后将结果按照顺序合并起来。
这里写图片描述

import java.util.Arrays;

/**
 * Created by Fearless on 2017/3/27.
 */
public class Merge {
    private static Comparable[] a={5,87,96,44,58,32};//测试数组
    private static Comparable[] aux;//原数组的拷贝数组

    /***
     * 测试算法
     * @param args
     */
    public static void main(String ... args){
        mergeSort(a);
        System.out.println("S"+Arrays.toString(a));
    }

    public static void mergeSort(Comparable[] a){
        int len=a.length;
        aux=new Comparable[len];//实例化数组,设置大小为排序数组的大小
        sort(a,0,(len-1));//进行排序,
    }

    /***
     * 进行归并排序
     * @param a 需要排序的数组
     * @param i 排序起始位置索引
     * @param i1 排序结束位置索引
     */
    private static void sort(Comparable[] a, int i, int i1) {
        if(i>=i1) return;//如果初始位置大于等于结束位置,不进行排序
        int m=i+(i1-i)/2;//设置中间值;
        sort(a,i,m);//对前半部分排序
        sort(a,m+1,i1);//对后半部分进行排序
        merge(a,i,m,i1);
       /* System.out.println("sort "+i+" "+m);
        System.out.println("sort "+(m+1)+" "+i1);
        System.out.println("merge "+i+" "+i1+" "+Arrays.toString(a));*/
    }

    /***
     * 合并两个相邻数组
     * @param a 原数组
     * @param i 前面数组的起始索引
     * @param m 前面数组的结束索引
     * @param i1 后面数组的结束索引
     */
    private static void merge(Comparable[] a, int i, int m, int i1) {
        //将要合并的数据全部放入aux中
        for(int j=i;j<=i1;++j){
            aux[j]=a[j];
        }
        //对数组进行遍历比较
        int index1=i;
        int index2=m+1;

        for(int k=i;k<=i1;++k) {
            //int t1=index1;
            //int t2=index2;
            if (index1 > m) {
                //如果第一个数组已经遍历结束,就把第二个数组的剩余数据跟在后面
                a[k]=aux[index2++];
            }else if(index2>i1){
                //如果第二个数组的数据已经遍历结束,就把第一个数组的剩余数据跟在后面
                a[k]=aux[index1++];
            }else if(less(aux[index1],aux[index2])){
                //如果a[index1]比a[index2]小,(如果做升序排序就取小的)
                a[k]=aux[index1++];
            }else{
                //如果a[index1]大于等于a[index2],(如果做升序排序就取小的)
                a[k]=aux[index2++];
            }
            //if(i==0 && i1==9)
            //System.out.println("add "+t1+" "+t2+" "+k+" \naux="+Arrays.toString(aux)+"\na="+Arrays.toString(a));
        }
    }
    //a是否小于b
    private static boolean less(Comparable a, Comparable b) {
        return a.compareTo(b)<0;
    }
}
自下而上的归并排序

思路:循序渐进,先两两比较,完后再将比较的结果按照顺序合并起来。

这里写图片描述

import java.util.Arrays;

/**
 * Created by Fearless on 2017/3/28.
 */
public class MergeBU {
    private static Comparable[] aux;//辅助数组
    private static Comparable[] a={5,87,96,44,58,32,25,1,77,69,36,44};//测试数组

    /***
     * 测试
     * @param args
     */
    public static void main(String ... args){
        sort(a);
        System.out.println(Arrays.toString(a));
    }
    /***
     * 排序算法
     * @param a
     */
    public static void sort(Comparable[] a){
        int len=a.length;
        aux=new Comparable[len];
        /*arrLen:需要归并的数组大小,初始大小为1,因为每次归并都是合并两个相邻数组,
        所以合并后大小比原大小扩大一倍*/
        for(int arrLen=1;arrLen<len;arrLen=arrLen*2){
            /*index1为归并的第一个数组的索引,因为一次是要归并两个数组,
            所以在一次归并结束后要跳过归并的两个数组的索引
             */
            for(int index1=0;index1<len-arrLen;index1+=arrLen*2){
                /*
                * index1+arrLen*2-1 为理论上第二个数组的最后一个数据的索引,
                * 但是很多情况下的数组长度不是2^n 所以最后一个数组的索引应该按照实际的长度来计算
                * 这样就需要对理论长度和实际长度做取最小操作,防止数组越界
                * */
                merge(a,index1,index1+arrLen-1,Math.min(index1+arrLen*2-1,len-1));
            }
        }
    }
    /***
     * 合并两个相邻数组
     * @param a 原数组
     * @param i 前面数组的起始索引
     * @param m 前面数组的结束索引
     * @param i1 后面数组的结束索引
     */
    private static void merge(Comparable[] a, int i, int m, int i1) {
        //将要合并的数据全部放入aux中
        for(int j=i;j<=i1;++j){
            aux[j]=a[j];
        }
        //对数组进行遍历比较
        int index1=i;
        int index2=m+1;

        for(int k=i;k<=i1;++k) {
            //int t1=index1;
            //int t2=index2;
            if (index1 > m) {
                //如果第一个数组已经遍历结束,就把第二个数组的剩余数据跟在后面
                a[k]=aux[index2++];
            }else if(index2>i1){
                //如果第二个数组的数据已经遍历结束,就把第一个数组的剩余数据跟在后面
                a[k]=aux[index1++];
            }else if(less(aux[index1],aux[index2])){
                //如果a[index1]比a[index2]小,(如果做升序排序就取小的)
                a[k]=aux[index1++];
            }else{
                //如果a[index1]大于等于a[index2],(如果做升序排序就取小的)
                a[k]=aux[index2++];
            }
            //if(i==0 && i1==9)
            //System.out.println("add "+t1+" "+t2+" "+k+" \naux="+Arrays.toString(aux)+"\na="+Arrays.toString(a));
        }
    }
    //a是否小于b
    private static boolean less(Comparable a, Comparable b) {
        return a.compareTo(b)<0;
    }
}

PS:CSDN 的markdown画图没有有道云笔记的舒服啊,是我不会用吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值