Java中的归并排序

归并排序


今天我们来说一说常见的七大排序中的最后一个----归并排序.
归并排序的思想就是大化小.

递归版本

首先我们要做的就是把数据一直对半分,直到分成了一组只有一个:
在这里插入图片描述
不知道兄弟们还记不记得之前我们说过的两个有序数组的合并?只有一个数据时,自然而然可以看成是有序的,然后我们就可以慢慢地合并了:
在这里插入图片描述

//合并的逻辑并不复杂,只是有些需要考虑:
//之前我们说了,数据都是对半分的,那么第一组就应该是前半段,第二组就是后半段
//这就必然涉及到中间的下标
    public void add(int[]arr,int left,int mid,int right){
        int[]tmp=new int[right-left+1];
        int s1=left;
        int s2=mid+1;
        int k=0;
        while (s1<=mid&&s2<=right){
            while (s1<=mid&&s2<=right&&arr[s1]<arr[s2]){
                tmp[k++]=arr[s1++];
            }
            while (s1<=mid&&s2<=right&&arr[s1]>arr[s2]){
                tmp[k++]=arr[s2++];
            }
        }
//当一组数据排好时,我们不知道另一组数据的情况,还是需要排一下的
        while (s1<=mid){
            tmp[k++]=arr[s1++];
        }
        while (s2<=right){
            tmp[k++]=arr[s2++];
        }
        //这里arr的下标需要处理的原因是因为,如果此时我们在后半段数据时
        //很有可能下标是不对应的,你能明白我的意思吗?前面会有left的一个空隙
        for (int i = 0; i < tmp.length; i++) {
            arr[i+left]=tmp[i];
        }
    }
    
    public void merge(int[]arr,int left,int right){
        if(left>=right)return;
        int mid=(left+right)/2;
        //先分
        merge(arr,left,mid);
        merge(arr,mid+1,right);
        //再合并
        add(arr,left,mid,right);
    }
    public void mergeSort(int[]arr){
        merge(arr,0,arr.length-1);
    }

非递归

    public void mergeSort1(int[]arr){
        int gap=1;
        //gap就表示每一次归并组内的个数,当归并整个数组长度时,就完了
        while(gap<=arr.length){
            for (int i = 0; i < arr.length-1; i+=gap*2) {
            //i就表示每次归并的起始
                int left=i;
                int mid=left+gap-1;
                if(mid>arr.length-1){
                    mid=arr.length-1;
                }
                int right=mid+gap;
                if(right>arr.length-1){
                    right=arr.length-1;
                }
                add(arr,left,right);
            }
           // 我们这里不需要自己分组是因为,我们就是从一组的情况下开始的
            //所以我们也要自己调整gap
            gap*=2;
        }
    }

好了,兄弟们,有了学习二叉树的知识,其实我们的归并排序就显得不是那么困难了,尤其是看完了我的这篇博客,你们应该会有一个更加清晰的认识吧!
百年大道,你我共勉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值