我无法弄清楚这种合并排序算法的问题

I can't figure out the problem with this merge sort algorithm

提问人:DineshK-1 提问时间:9/23/2023 最后编辑:chqrlieDineshK-1 更新时间:9/24/2023 访问量:68

问:

我正在尝试学习数据结构和算法,我一直很享受这个过程。我开始研究 Merge Sort 的工作原理,并希望实现它。这是我的代码,出于某种原因,我无法弄清楚为什么我的输出搞砸了!

    public static void Merge(ArrayList<Integer> arr, int low, int mid, int high) {
        int left = low;
        int rightPointer = mid + 1;

        ArrayList<Integer> new_list = new ArrayList<>();

        while (left <= mid && rightPointer <= high) {
            if (arr.get(left) <= arr.get(rightPointer)) {
                new_list.add(arr.get(left));
                left++;
            } else {
                new_list.add(arr.get(rightPointer));
                rightPointer++;
            }
        }

        while (left <= mid) {
            new_list.add(arr.get(left));
            left++;
        }

        while (rightPointer <= high) {
            new_list.add(arr.get(rightPointer));
            rightPointer++;
        }

        for (int ele : new_list) {
            System.out.print(ele + " ");
        }
        System.out.println();
    }

    public static void MergeSort(ArrayList<Integer> arr, int low, int high) {
        if (low >= high)
            return;
        int mid = (low + high) / 2;

        MergeSort(arr, low, mid);
        MergeSort(arr, mid + 1, high);
        Merge(arr, low, mid, high);
    }

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>(
                Arrays.asList(25, 10, 3, 50, 24, 14, 8, 22, 35, 42, 10, 5, 18, 29, 50));

        MergeSort(list, 0, list.size() - 1);
    }

这是我的输出,(打印合并函数的每次调用):

10 25 
3 50 
3 25 10 50 
14 24 
8 22 
8 22 24 14 
24 14 8 22 25 10 3 50 
35 42 
5 10 
10 5 35 42 
18 29 
18 29 50 
18 29 35 42 10 5 50 
25 10 3 35 42 10 5 18 29 50 24 14 8 22 50

我在这里做错了什么?我试过问 chatGPT,得到的答复是它无法从给定的代码中找到任何错误!

我尝试在 python 上重写整个代码,并发现列表在插入新“排序”数组时没有正确排序。但我不知道如何解决这个问题。

Java 算法 mergesort 分而治之

评论

2赞 f1sh 9/23/2023
您永远不会修改原始列表。你的方法创建一个,把元素放在那里,然后把它扔掉,你没有用它做任何事情。出于某种原因,chatGPT 错过了这一点。MergeArrayList<Integer> new_list = new ArrayList<>();
0赞 DineshK-1 9/23/2023
是的,我正在使用一个新的临时列表来检查算法是否通过附加较小的元素来工作。但是它的分类方式存在问题,我无法弄清楚为什么:(
1赞 f1sh 9/23/2023
该算法不适用于临时列表。每次递归调用都会创建一个临时列表,然后将其丢弃。调用堆栈上的其他调用方法不会看到任何效果,因此不会进行排序。Merge
0赞 DineshK-1 9/23/2023
不,你错过了重点,我没有打印未经修改的数组。我正在打印临时列表,看看排序是否真的有效。我已经更新了代码以修改原始列表,但它仍然不起作用。我添加了一个新的 k 整数并替换了这样的元素arr.set(k++, arr.get(left++));
0赞 Old Dog Programmer 9/24/2023
我已将代码更新为...然后编辑问题以显示更新的代码。

答:

1赞 marcinj 9/24/2023 #1

您的代码看起来几乎是正确的,您只是没有使用排序的元素更新原始数组。将元素合并到新列表中后,需要将它们复制回原始数组中。我已经测试了您的代码,在方法末尾添加此循环后看起来正确:Merge

    for (int i = 0; i < new_list.size(); i++)
        arr.set(low + i, new_list.get(i));