吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1481|回复: 7
收起左侧

[Java 转载] 排序算法----归并算法遇坑史

[复制链接]
逸帅 发表于 2021-3-23 16:58
本帖最后由 逸帅 于 2021-3-23 17:00 编辑

1、项目场景:

记录一次归并排序遇坑史<br/>
一天天的,啥事也没干,尽遇坑去了

2、问题描述:


    []希尔排序在最开始给方法传递左右索引的时候,左边传递的是0,右边传递的是length-1
    [
    ]左右索引在比较的时候,没加索引和边界值重合的情况
    []定义数组的时候,考虑索引和长度,数组的长度 = 最大索引 + 1
    [
    ]遍历数组的时候,长度不要-1,长度不要-1,长度不要-1!

3、原因分析:


    []将数组分割成两份的时候,中间值是在左边的数组中的,所以右边开始的索引,应该是mid(中间值的索引)+1
    [
    ]因为在最开始传值的时候,右边的索引就是length-1,所以是可以直接等于边界值的,不加=,就会导致明明排序好了的元素,复制到原数组的时候,无法覆盖完,会存在最后一位不覆盖的情况
    []定义一个temp临时数组的空间大小的时候,right-left之后,还要+1,一位right-left是索引的大小,但是直接定义new   int[]的时候,里面填入的是长度,所以要填入new int[right - left + 1]
    [
    ]数组遍历的时候,不要i < arr.length - 1

4、解决方案:

1、左边的取值是【left,mid】,右边的取值范围是【mid+1,right】

public static void sortArray(int[] initial, int left, int right) {
        if(left < right){
            int mid = (left + right) / 2;
            //使用了递归:
            // mid+1是因为,length-1,代表中间值在左边的数组中,
            // 例如:数组长度为8,则right=7,mid=7/2 =3
            //0-3是左边的数组,右边的自然是mid+1 = 3+1 =4
            sortArray(initial, left, mid);
            sortArray(initial, mid + 1, right);
            mergetSort(initial, left, right, mid);
        }else {
            return;
        }
    }

2、在每个比较的地方,加上 = 号

//这里可以取到边界值,因为在传值的时候,传的就是length-1,数组不会越界
        while (leftIndex <= mid && rightIndex <= right) {
            if (initial[leftIndex] < initial[rightIndex]) {
                //左边的小,就把左边的数放到新的数组中,以此类推直到左边或者右边的索引,到达中间的位置
                temp[t++] = initial[leftIndex++];
            } else {
                temp[t++] = initial[rightIndex++];
            }
        }
        //左边的索引依然没到达中间索引的位置,说明右边的索引已经达到了边界
        //此时把左边所以的数,都依次放到temp数组中即可
        while (leftIndex <= mid) {
            temp[t++] = initial[leftIndex++];
        }
        while (rightIndex <= right){
            temp[t++] = initial[rightIndex++];
        }
  1. 定义temp的空间大小的时候,要【right-left+1】
//这里要+1,是因为这里是定义temp的长度,right-left只是最大的索引,长度要+1
        int[] temp = new int[right - left + 1];
  1. 去掉length后面的  -1
for (int i = 0; i < temp.length; i++) {
            initial[i+left] = temp[i];
        }

5、完整的代码:

package com.yishuai.sort;

import java.util.Arrays;

/**
 * @AuThor yishuai
 * @description 归并排序
 * @date 2021/3/23 11:12
 */
public class Merget {
    public static void main(String[] args) {
        int[] initial = {5, 9, 2, 8, 6, 3, 1, 4, 7};

        sortArray(initial,0,initial.length - 1);
        System.out.println(Arrays.toString(initial));
    }

    /**
     * @description 分割数组
     */
    public static void sortArray(int[] initial, int left, int right) {
        if(left < right){
            int mid = (left + right) / 2;
            //使用了递归:
            // mid+1是因为,length-1,代表中间值在左边的数组中,
            // 例如:数组长度为8,则right=7,mid=7/2 =3
            //0-3是左边的数组,右边的自然是mid+1 = 3+1 =4
            sortArray(initial, left, mid);
            sortArray(initial, mid + 1, right);
            mergetSort(initial, left, right, mid);
        }else {
            return;
        }
    }

    /**
     * @Param left    数组最左边的索引
     * @param right   数组最右边的索引
     * @param mid     中间的索引
     * @description 归并数组
     */
    public static void mergetSort(int[] initial, int left, int right, int mid) {
        //这里要+1,是因为这里是定义temp的长度,right-left只是最大的索引,长度要+1
        int[] temp = new int[right - left + 1];

        //t作为temp数组的索引
        int t = 0;
        //左右两个索引,都是从数组的最左边开始遍历
        int leftIndex = left;
        //mid+1是因为,length-1,代表中间值在左边的数组中,
        // 例如:数组长度为8,则right=7,mid=7/2 =3
        //0-3是左边的数组,右边的自然是mid+1 = 3+1 =4
        int rightIndex = mid + 1;
        //这里可以取到边界值,因为在传值的时候,传的就是length-1,数组不会越界
        while (leftIndex <= mid && rightIndex <= right) {
            if (initial[leftIndex] < initial[rightIndex]) {
                //左边的小,就把左边的数放到新的数组中,以此类推直到左边或者右边的索引,到达中间的位置
                temp[t++] = initial[leftIndex++];
            } else {
                temp[t++] = initial[rightIndex++];
            }
        }
        //左边的索引依然没到达中间索引的位置,说明右边的索引已经达到了边界
        //此时把左边所以的数,都依次放到temp数组中即可
        while (leftIndex <= mid) {
            temp[t++] = initial[leftIndex++];
        }
        while (rightIndex <= right){
            temp[t++] = initial[rightIndex++];
        }
        //此时temp就是排序好之后的数组
        System.out.println(Arrays.toString(temp));
        for (int i = 0; i < temp.length; i++) {
            initial[i+left] = temp[i];
        }
    }
}

免费评分

参与人数 2吾爱币 +2 热心值 +1 收起 理由
云观水 + 1 用心讨论,共获提升!
tobiasaxzc + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

红蓝黄 发表于 2021-3-23 17:09
感谢大神分享
沧浪风澜 发表于 2021-3-23 17:19
学习了!感谢分享!对半路出家但是喜欢计算机的人来说,对算法又爱又恨
永远爱高木同学 发表于 2021-3-23 17:24
Calvin 发表于 2021-3-23 17:37

学习了!感谢分享!对半路出家但是喜欢计算机的人来说,对算法又爱又恨
无名氏wyw 发表于 2021-3-23 19:33
奇怪的mergesort
明明一个函数就能搞定的事干嘛非得麻烦栈
syz17213 发表于 2021-3-23 20:11
感谢分享,来学习
云观水 发表于 2021-3-23 20:17
感谢分享,大佬NB
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-25 18:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表