归并排序

思想

(1)尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是
1为止。

(2)将相邻的两个子组进行合并成一个有序的大组;
(3)不断的重复步骤2,直到最终只有一个组为止。
归并排序_第1张图片

API设计

归并排序_第2张图片
归并排序_第3张图片

归并的原理

定义一个辅助数组 和两个辅助指针
归并排序_第4张图片
归并排序_第5张图片
归并排序_第6张图片

代码实现

import org.junit.Test;

import java.util.Arrays;

/**
 * 归并排序
 */
public class Merge {
     
    /**
     * 完成归并操作需要的辅助数组assist
     */
    private static Comparable[] assist;
    /**
     * 对数组a中的元素进行排序
     */
    public static void sort(Comparable[] a){
     
        //对辅助数组进行初始化
        assist=new Comparable[a.length];
        int lo=0;
        int hi=a.length-1;
        sort(a,lo,hi);
    }

    /**
     * 对数组a中从lo到hi的元素进行排序
     */
    private static void sort(Comparable[]a ,int lo,int hi){
     
        //给递归限制临界值
        if(lo>=hi){
     
            return;
        }
        int mid=(lo+hi)/2;
        //对左边lo到mid之间的元素进行排序
        sort(a,lo,mid);
        //对右边mid+1到hi 之间的元素进行排序
        sort(a,mid+1,hi);

        //将lo~mid  数组 和mid+1 ~ hi 数组进行合并
        merge(a,lo,mid,hi);
    }
    /**
     * 对数组中,从lo到mid为一组,从mid+1到hi为一组,对这两组数据进行归并
     */
    private static void merge(Comparable[]a,int lo,int mid,int hi){
     
        //定义一个指针,指向assist数组中开始填充数据的索引
        int i=lo;
        //定义一个指针,指向左边小组数据的第一个元素
        int p1=lo;
        //定义一个指针,指向右边小组数据的第一个元素
        int p2=mid+1;


        //比较左边小组和右边小组中的元素大小,哪个小,就把哪个数据填充到assist数组中
        while (p1<=mid && p2<=hi){
     
            if(less(a[p1],a[p2])){
     
                assist[i++]=a[p1++];
            }else {
     

                assist[i++]=a[p2++];
            }
        }
        /**
         * 上面的循环结束,判断结束条件
         * 如果是p1>mid,证明左边小组中的数据已经归并完毕
         * 如果是p2>hi,证明右边小组中的数据已经归并完毕
         */


        //所以需要把未填充完毕的数据继续填充到assist中
        // 下面两个循环,只会执行其中的一个


        //遍历,如果p1的指针没有走完,那么顺序移动p1指针,把对应的元素放到辅助数组的对应索引处
        while (p1<=mid){
     
            assist[i++]=a[p1++];
        }

        //遍历,如果p2的指针没有走完,那么顺序移动p2指针,把对应的元素放到辅助数组的对应索引处
        while (p2<=hi){
     
            assist[i++]=a[p2++];
        }

        //把辅助数组中的元素拷贝到原数组中
        for (int index = lo; index <=hi; index++) {
     
            a[index]=assist[index];
        }
    }
    /**
     * 比较v元素是否小于w元素
     */
    private static boolean less(Comparable v,Comparable w){
     
        return v.compareTo(w)<0;
    }
    @Test
    public void test(){
     
        Integer[] a={
     9,8,7,5,4,3,2,1};
        sort(a);
        System.out.println(Arrays.toString(a));
    }
}

归并排序的缺点

需要申请额外的数组空间,导致空间复杂度提升,是典型的以空间换时间的操作。

你可能感兴趣的:(算法,排序算法,算法,排序算法)