超详解排序算法之(六)归并排序

归并排序

归并排序简介

归并排序是利用归并的思想实现排序的方法,这个排序算法采用了经典的分治策略【所谓分治法,先将问题成一些小的问题然后递归求解,的处理是将分的阶段中得到的各个答案“修补”在一起,从而实现分而治之。 】

看图释义

在这里插入图片描述

我们第一步递归的将原始数组分为不可再分的单元,在这步我们需要将拿到的数组进行分割,每一次都将分组分为两组,二分法,直到数组分割成一个个的元素单元。
第二步,归并到一起是归并算法的精髓,我们从最小单元开始合并,每一次合并就是一次有序化。通过log2N次归并处理就得到我们的有序化序列。

代码实现

最终结果代码

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {8,4,5,7,1,3,6,2};
        int[] temp = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println("归并排序的结果:"+ Arrays.toString(arr));

    }
    public static void mergeSort(int[] arr,int left,int right,int[] temp){
        if(left<right){
            int mid = (left+right)/2;
            //向左递归
            mergeSort(arr,left,mid,temp);
            //向右递归
            mergeSort(arr,mid+1,right,temp);
            //合并
            merge(arr,left,mid,right,temp);
        }
    }

    /**
     *
     * @param array 原始数组
     * @param left 左边有序序列的初始索引
     * @param mid 中间索引
     * @param right 右边索引
     * @param temp 临时数组
     */
    public static void merge(int[] array,int left,int mid,int right,int[] temp){
        int i=left; //左边数组的初始下标
        int j=mid+1; //右边数组的初始下标
        int t=0;//指向temp数组的当前索引

        //(一)
        //先把左右两边有序数组按照柜子额填充到temp数组
        while (i<= mid && j <=right){
            if(array[i]<=array[j]){
                temp[t]=array[i];
                i++;
                t++;

            }
            else {
                temp[t]=array[j];
                j++;
                t++;
            }

        }
        //(二)
        // 把有剩余数据的一边的数据一次填充到temp中去
        while(i<=mid){
            temp[t]=array[i];
            t++;
            i++;
        }
        while(j<=right){
            temp[t]=array[j];
            t++;
            j++;
        }
        //(三)
        // 把temp拷贝到array中去
        t=0;
        int tempLeft=left;
        while (tempLeft<=right){
            array[tempLeft]=temp[t];
            t+=1;
            tempLeft+=1;
        }

    }
}

代码实现过程详解

先进行分组
分组第一步我们先获取一个中间位置的元素,将元素分组,分的步骤实现,当每一个分组都不可再分,也就是说对于当前的分组左下标不小于右下标的时候这个分组就不可再分【递归的基准条件】

/**
     *
     * @param arr 原始数组
     * @param left 组内左下标
     * @param right 组内右下标
     * @param temp 临时数组
     */
    public static void mergeSort(int[] arr,int left,int right,int[] temp){
    	//左下标
        if(left<right){
            int mid = (left+right)/2;
            //向左递归
            mergeSort(arr,left,mid,temp);
            //向右递归
            mergeSort(arr,mid+1,right,temp);
            //合并
            merge(arr,left,mid,right,temp);
        }
    }

合并处理
我们从最后一步的合并来进行分析处理,左右两个分组依次从对应组的下标进行遍历,将对应的小的值存放在新的数组中,直到一个数组的数据全部遍历完,另一个数组的元素直接插入新的数组中。

/**
     *
     * @param array 原始数组
     * @param left 左边有序序列的初始索引
     * @param mid 中间索引
     * @param right 右边索引
     * @param temp 临时数组
     */
    public static void merge(int[] array,int left,int mid,int right,int[] temp){
        int i=left; //左边数组的初始下标
        int j=mid+1; //右边数组的初始下标
        int t=0;//指向temp数组的当前索引

        //(一)
        //先把左右两边有序数组按照柜子额填充到temp数组
        while (i<= mid && j <=right){
            if(array[i]<=array[j]){
                temp[t]=array[i];
                i++;
                t++;

            }
            else {
                temp[t]=array[j];
                j++;
                t++;
            }

        }
        //(二)
        // 把有剩余数据的一边的数据一次填充到temp中去
        while(i<=mid){
            temp[t]=array[i];
            t++;
            i++;
        }
        while(j<=right){
            temp[t]=array[j];
            t++;
            j++;
        }
        //(三)
        // 把temp拷贝到array中去,注意一下这个处理,要涉及到其他分组的数量大于2的情况
        t=0;
        int tempLeft=left;
        while (tempLeft<=right){
            array[tempLeft]=temp[t];
            t+=1;
            tempLeft+=1;
        }

    }

测试结果

在这里插入图片描述

我们同样用8W个数据进行一把效率的验证

在这里插入图片描述

秒级的处理速度,感兴趣的小伙伴同样可以试试将时间显示为毫秒级查看一下。
另外将测试数据扩大10倍、100倍看看实际的耗时。

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值