简体   繁体   English

合并排序无法递归工作

[英]Merge sort doesn't work reursively

I want to build an algorithm where I'm sorting a linked list via merge sort. 我想建立一种算法,通过合并排序对链表进行排序。 Here the code: 这里的代码:

private Item mergeSort(Item l){
    //if the list contains of just one item we don't have to sort it anymore
    if(l.next == null) return l;
    //divide your list in two parts and get both starts of both lists
    Item middle = getMidItem(l);
    Item start1 = l;
    Item start2 = middle.next;
    middle.next = null;
    //process recursively the same process but with the both new lists until both lists only contain of one item
    Item item1 = mergeSort(start1);
    Item item2 = mergeSort(start2);
    //if both lists are sorted put them together
    return merge(item1, item2);
}

This function works recursively. 此函数递归工作。 First, if it hasn't another element, I return the current one and stop the function. 首先,如果没有其他元素,则返回当前元素并停止该函数。 If it has more than one element, I determine the middle of the element (getMidItem works properly I've debugged it several times) and divide both lists in two parts. 如果它具有多个元素,则确定该元素的中间(我已经多次调试了getMidItem正常工作),并将两个列表分为两部分。 After that, I recursively open the function again and do it for both lists now until the list contains of just one element. 之后,我再次递归打开该函数,并立即对两个列表进行操作,直到列表仅包含一个元素。 If this going to happen, I return all elements and merge them. 如果发生这种情况,我将返回所有元素并合并它们。

The merge function determines which element is the smaller one, puts the references of the smaller one on the front and the bigger one on the end, until it has run over the whole list. merge函数确定哪个元素较小,将较小元素的引用放在前面,将较大元素的引用放在最后,直到它遍历整个列表为止。 The problem in here is, my whole structure. 这里的问题是我的整个结构。 If I run it he will get to one point, where the lists contains of just one element and he returns it, saves it and merges only in the last recursion step and stops it. 如果我运行它,他将到达一点,列表仅包含一个元素,然后他将其返回,保存并仅在最后一个递归步骤中合并并停止它。 And in the end, I don't get my list, but only the first element of the list. 最后,我没有得到列表,而只有列表的第一个元素。

I realized that this isn't going to work, but I have actually no clue, how I can rewrite it, so that it does what I want. 我意识到这行不通,但实际上我不知道如何重写它,以便它可以执行我想要的操作。 I know how merge sort does work, but I don't know how to implement it, like this way. 我知道合并排序的工作原理,但是我不知道如何实现它,就像这样。 And before somebody says, that "it is hard that way, just rewrite the method body and return the first, the middle and the last one or do it with an array", I have to do it that way. 在有人说“那很难,只要重写方法主体并返回第一个,中间和最后一个,或者使用数组来完成”,我就必须这样做。 It's homework. 这是家庭作业。

Here is the merge function: 这是merge功能:

public static Item merge(Item a, Item b){
    //if both items are null return null, if one is null return the other
    if(a == null && b == null) return null;
    else if(a == null && b != null) return b;
    else if(a != null && b == null) return a;
    else{
        //create minimum and check if 'a' or 'b' is smaller and set it to minimum
        Item min = null;
        //if a is smaller than b, a should be returned and the next item of 'a' should be 'b'
        if(a.value.compareTo(b.value) < 0){
            //the next reference of the smaller element should be the bigger one
            min = a;
            a = a.next;
        }
        else{
            //same but the other way around
            min = b;
            b = b.next;

        }
        //you create the next reference of the minimum 
        Item p = min;
        if(a != null && b != null){
            //you iterate through the whole list and put the references of the smaller one on the front and the bigger one behind
            while(a.next != null && b.next != null){
                if(a.value.compareTo(b.value) < 0){
                    p.next = a;
                    a = a.next;
                }
                else{
                    p.next = b;
                    b = b.next;
                }
            }
        }
        return p;
    }
}

You have a logical problem with your merge(...) method when merging the lists: 合并列表时,您的merge(...)方法存在逻辑问题:

   if(a != null && b != null){ // PROBLEM OCCURS HERE
        //you iterate through the whole list and put the references of the smaller one on the front and the bigger one behind
        while(a.next != null && b.next != null){ // AND HERE
            if(a.value.compareTo(b.value) < 0){
                p.next = a;
                a = a.next;
            }
            else{
                p.next = b;
                b = b.next;
            }
        }
    }

You check whether a != null && b != null . 您检查a != null && b != null What if only one list is null ? 如果只有一个列表为null怎么办? In this case you neglect content from the second list and therefore loose data. 在这种情况下,您将忽略第二个列表中的内容,因此会丢失数据。 You have to account for the fact that one of the lists may run out of data (ie is null ) while the other list still holds elements. 您必须考虑以下事实:其中一个列表可能用完了数据(即null ),而另一个列表仍包含元素。

Make a pen & paper-test with your mergesort and an already sorted list. 用您的mergesort和已排序的列表进行笔和纸测试。 This should reveal the problem. 这应该可以揭示问题。

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

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