排序算法——归并排序

6.归并排序

(1)基本思想:

利用归并的思想实现排序方法。该算法采用分治策略。(分治法将问题分成一些小问题,然后递归求解,而治的阶段就是降分的阶段得到的各答案“修补”在一起,即分而治之)。

(2)归并排序思想示意图:

 

 

图解说明:

a.第一步——>分:mid=left+right,将整个待排序列分为左子树 [left,mid] 和右子树 [mid+1,right]两个待排序列,再继续将[left,mid]和 [mid+1,right]递归分成更多的子序列,递归终止条件为:left > right

b.第二步——>治:

         ① 将已经递归分成的最小的左子树序列(只含有一个待排数据)与最小的右子树序列从第一个元素进行数据比较,如果左边有序序列的当前元素数据小于右边有序序列的当前元素数据,则将左边有序序列的当前元素填充到temp[]数组中;反之,则将右边有序序列的当前元素数据填充到temp[]数组中。

         ② 若左边的有序序列的元素已经全部填充到temp[] 数组中,则将右边有序序列剩余的元素按照顺序逐个放入temp[]数组中;若右边有序序列的元素已经全部填充到temp[] 数组中,则将左边有序序列剩余的元素按照顺序逐个放入temp[]数组中

c.第三步:将temp[]数组 copy 原来的数组中。【注意并不是copy最后一次的temp[]数组,而是每次递归时都要进行copy】

(3)代码实现

//归并排序
    public void mergetSort(int[] arr,int left,int right,int[] temp) {
        //分+和:
        int mid = (left +right) / 2;
        //分:
        if(left < right) {
            //左边序列:
            mergetSort(arr,left,mid,temp);
            //右边序列:
            mergetSort(arr,mid + 1,right,temp);
            //和:
            merget(arr,left,right,mid,temp);

        }

    }

      //合并:
    /**
     * 合并成为有序的序列:
     * @param arr 待排的序列
     * @param left 左边序列的初始索引【左边序列的第一个元素】
     * @param right 右边序列的初始索引【右边序列的最后一个元素】
     * @param mid 中间索引【左边序列的最后一个元素】
     * @param temp 中转的数组
     */
    public void merget(int[] arr,int left,int right,int mid,int[] temp) {
        int i = left; //初始化为i,左边有序序列的初始索引
        int j = mid + 1; //初始化为j,右边有序序列的初始索引
        int t = 0;//指向中转数组的当前索引

        //第一步
        //先将左右两边的数据按照规则填充到中转数组temp[]中
        //直到左右两边有一边的数据已经全部填充完了
        while (i <= mid && j <= right) {
            //左右两边的数据进行比较,如果左边有序序列的当前元素,小于右边有序序列的当前元素
            //则将左边的当前元素填充到中转数组temp[]中
            //然后t++,i++
            if(arr[i] < arr[j]) {
                temp[t] = arr[i];
                t += 1;
                i += 1;
            }else { //如果右边的当前元素小于左边的当前元素,则同理。//然后 j++,t++
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }

        //当右边的有序序列已经全部填充在中转数组中,左边有序序列还有元素剩余
        //就将左边的所有元素按照原本的有序顺序依次填充到中转数组中
        while(i <= mid) {
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }
        //当右左边的有序序列已经全部填充在中转数组中,右边有序序列还有元素剩余
        //同理
        while(j <= right) {
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }

        //第二步
        //再将中转数组temp[]中的元素全部copy到原来的数组中
        //注意并不是每次都是copy所有,不是每次都是拷贝left到right的所有元素
        t = 0;
        int tempLeft = left;
        //第一次合并:tempLeft = 0,right = 1;第二次合并:tempLeft = 2,right = 3;·····
        //最后一次合并:tempLeft = left,right = right;
        while(tempLeft <= right) {
            arr[tempLeft] = temp[t];
            tempLeft += 1;
            t += 1;
        }

    }

其他排序算法请转  小何小何h的博客_CSDN博客-领域博主

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值