学习笔记-归并排序

归并排序

将一个一维数组从小到大排序。归并排序采用了一种化繁为简、分而治之的思想。总的来说,是把一个数组先不断拆分,直到拆分到一个一个单独的元素,再把他们逐渐合并起来。这里边用到了递归回溯。
在这里插入图片描述

合并思路

在这里插入图片描述

先说合并的思路:合并时,将两个有序数组合并为一个,需要一个临时数组。先比较两数组的第一数字大小,把小的放入临时数组,然后比较小的数的后一位数与之前数的大小,同样把小的放在临时数组里,就这样一直比较,小的入临时数组,大的保留,索引++,然后再比较。直到两数组有一个到底或都到底。结束后,如果两数组有一个还没到底,就把它剩余的数直接加入临时数组。最后把有序的临时数组赋给原数组。
这个方法需要的参数有,要排序的原数组arr,左边有序序列的初始索引left(但不一定是原数组的最左索引),中间索引mid也就是第二个序列的初始索引之前的一位,右边索引right也就是第二个序列的最右索引(但不一定是原数组的最右索引),还有中间数组temp。

  1. 先把左右两边(有序)的数据按照规则填充到 temp 数组,直到左右两边的有序序列,有一边处理完毕为止。如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素,即将左边的当前元素,填充到 temp 数组,反之,将右边有序序列的当前元素,填充到 temp 。
  2. 把有剩余数据的一边的数据依次全部填充到 temp,左边的有序序列还有剩余的元素,就全部填充到 temp,右边的有序序列还有剩余的元素,就全部填充到 temp。
  3. 将 temp 数组的元素拷贝到 arr。

代码

 /**
     * 合并方法
     * @param arr 原数组
     * @param left 第一个有序数组开头
     * @param mid 第二个有序数组开头
     * @param right 原数组结尾
     * @param temp 临时数组
     */
    private static void merge(int[] arr,int left,int mid,int right,int[] temp){
        int i=left;
        int j=mid+1;
        int t=0;
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[t]=arr[i];
                t++;
                i++;
            }else {
                temp[t]=arr[j];
                t++;
                j++;
            }
        }

        while (i<=mid){
            temp[t]=arr[i];
            t++;
            i++;
        }
        while (j<=right){
            temp[t]=arr[j];
            t++;
            j++;
        }

        t=0;
        for (int k = left; k <=right; k++) {
            arr[k]=temp[t];
            t++;
        }

    }

分离+合并思路

将数组不断拆分,也就是每次把数组一分为二,mid每次等于首尾相加除2,因为索引是从0到长度-1,所以这个mid实际上指向第二数组头的前一位。采用递归,退出递归的条件是分到每组只剩下2个数,也就是保证每次left<right,left和right每次变化,分别表示小数组的最左和最右索引,当他们相等时就代表数组分到了只剩下一个元素。
先拆分左,再拆分右,然后合并。这里有点像栈的结构,假如有8个数,顺序是先拆到03,01,合并01,拆23,合并23,合并03,拆47,45,合并45,拆67,合并67,合并47,合并07。

代码

 /**
     * 分+和的方法
     * @param arr
     * @param left
     * @param right
     * @param temp
     */
    private 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);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值