简体   繁体   English

我的合并排序代码有什么问题?

[英]What is wrong with my Merge Sort code?

I'm having trouble with Merge Sort in my computers class. 我的计算机课上的合并排序出现问题。 I keep getting either errors or the original ArrayList returned. 我一直收到错误或返回原始ArrayList。

I believe that Merge Sort involves splitting an array(list) in half recursively until there is only one element left, then, working from those individual elements, merging them in sorted order. 我认为,合并排序涉及将数组(列表)递归拆分为一半,直到只剩下一个元素,然后从这些单独的元素开始工作,将它们按排序顺序合并。 This continues until the array(list) has been sorted. 这一直持续到对数组(列表)进行排序为止。 As for the actual sorting part, I am trying to insert into a new ArrayList the higher value between the two halves until they are both empty, in which case the filled ArrayList is now sorted. 至于实际的排序部分,我试图将新的两半之间的较高值插入到新的ArrayList中,直到它们都为空为止,在这种情况下,现在对填充的ArrayList进行排序。

Here's my current code: 这是我当前的代码:

public static ArrayList<Integer> mergesort(ArrayList<Integer> arr) {

    // Base case: if size of ArrayList is 1, return it.
    if (arr.size() < 2) {
        return arr;
    }

    // Else: Find the middle index.
    int middle = (arr.size() - 1) / 2;

    // Split into left and right halves.
    ArrayList<Integer> leftHalf = new ArrayList<Integer>();
    for (int i = 0; i < middle; i++)
        leftHalf.add(arr.get(i));

    ArrayList<Integer> rightHalf = new ArrayList<Integer>();
    for (int j = middle; j < arr.size(); j++)
        rightHalf.add(arr.get(j));

    // Recurse using the halves.
    mergesort(leftHalf);
    mergesort(rightHalf);

    // Sort and merge the two halves.
    return merge(leftHalf, rightHalf, arr);
}

// Merge two halves and sort them, and put the sorted values into the ArrayList sorted.
public static ArrayList<Integer> merge(ArrayList<Integer> arr1, ArrayList<Integer> arr2, ArrayList<Integer> sorted) {

    // While the ArrayLists are not empty, add sorted elements to ArrayList sorted.
    while (arr1.size() > 0 && arr2.size() > 0) {

        // If the first element in A is greater than the first in B, remove A and add to ArrayList sorted.
        if (arr1.get(0) >= arr2.get(0)) {
            sorted.add(arr1.get(0));
            arr1.remove(0);
        }
        // Else, remove from B and add to ArrayList sorted.
        else {
            sorted.add(arr2.get(0));
            arr2.remove(0);
        }
    }

    // If there're still elements in A due to arr being odd
    // add them to C since they will be the largest.
    if (arr1.size() > 0)
        sorted.add(arr1.get(0));

    return sorted;
}

I would appreciate any help, but please don't give me a full implementation of the Merge Sort, since I want to actually learn how to do this for the future. 我将不胜感激,但是请不要给我完整的“合并排序”实现,因为我想实际学习将来如何做。

Two immediate problems I see. 我看到了两个迫在眉睫的问题。

First, you have infinite recursion. 首先,您具有无限递归。 Say you pass in a 4-value list and print your list size and middle values, you'll get: 假设您传递一个4值列表并打印列表大小和中间值,您将获得:

size 4, middle 1 size 3, middle 1 size 2, middle 0 size 2, middle 0 size 2, middle 0 ... to infinity

Remember that Java is aleardy doing integer division in your code. 请记住,Java在代码中执行整数除法已相当可行。

Second, you're passing the arr parameter from mergesort to merge , nothing is ever getting removed from it. 其次,您要将arr参数从mergesortmerge ,因此什么也不会被删除。 So even if you made it past the infinite recursion you'd still end up with a larger list in the end, your original list plus anything you've .add() ed to it 因此,即使您经过了无限递归,您最终还是会得到一个更大的列表,这是原始列​​表以及您已经.add()编辑的任何内容

As mentioned by MarquisDeMizzle, so that middle == 1 when arr.size() == 1. 正如MarquisDeMizzle提到的那样,当arr.size()== 1时,中间== 1。

    int middle = arr.size() / 2;

After main merge loop copy any remaining elements, and since you don't know if arr1 or arr2 go empty first, check both: 在主合并循环之后,复制所有剩余元素,并且由于您不知道arr1或arr2首先变空,因此请同时检查以下两项:

    // copy any remaining elements
    while (arr1.size() > 0)
        sorted.add(arr1.get(0));

    while (arr2.size() > 0)
        sorted.add(arr2.get(0));

If interested, you might want to learn bottom up merge sort. 如果有兴趣,您可能想学习自下而上的合并排序。 It skips all the recursion and just starts off assuming an array with n elements is n runs of size 1, just using indexing to do the merge back and forth between the original and a temporary array. 它会跳过所有递归操作,并假设包含n个元素的数组的大小为n次运行,并且只是使用索引在原始数组和临时数组之间来回合并,就开始了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM