Java合并仅在首先添加最小数字时对链接列表排序进行排序

当我在链接列表中插入数字时,它只会在添加到它的第一个数字最小时对所有内容进行排序.这是我得到的意外行为:

我按此顺序插入数字 – 200,25,473,23,390

如果我按照上面那样对列表进行排序并显示它,我得到这个–200,390,473

如果我将200更改为900然后对列表进行排序,则仅显示900

它只适用于我将200更改为列表中的最小数字,如1(或任何小于23),然后它给我正确的输出1,23,25,390,473

对于链表,我在列表的后面插入元素,这是代码:

public void insertAtBack(IntegerElement elem) {
    if (isFull()) {
        System.out.println("Unable to insert node into full list");
    } else {
        Node temp = new Node(elem);
        if (isEmpty()) {
            head = temp;
        } else {
            Node current = head;
            while (current.getLink() != null) {
                current = current.getLink();
            }
            current.setLink(temp);
        }
    }

}

这是我用来合并排序的代码:

public Node getMiddle(Node node) {
    if (node == null) 
        return node;

    Node fastptr = node.getLink(); 
    Node slowptr = node; 

    // Move fastptr by two and slow ptr by one 
    // Finally slowptr will point to middle node 
    while (fastptr != null) { 
        fastptr = fastptr.getLink(); 
        if(fastptr != null) { 
            slowptr = slowptr.getLink(); 
            fastptr = fastptr.getLink(); 
        } 
    } 

    return slowptr; 
}

public Node merge(Node left, Node right)  { 

    Node tempHead = new Node(), curr;

    curr = tempHead;

    while(left != null && right != null) {
        if(left.getData().getValue() <= right.getData().getValue()) {
            curr.setLink(left);
            left = left.getLink();
        }else {
            curr.setLink(right);
            right = right.getLink();
        }

        curr = curr.getLink();
    }

    curr.setLink((left == null) ? right : left);

    return tempHead.getLink();

}

/**
 * This method utilizes merge sort algorithm
 * 
 * @param node - Pass in head first
 * 
 */
public Node sort(Node node) {
    // Base case : if head is null 
    if (node == null || node.getLink() == null)
        return node; 

    // get the middle of the list 
    Node middle = getMiddle(node);
    Node nextofmiddle = middle.getLink();

    // set the next of middle node to null 
    middle.setLink(null);

    // Merge the left and right lists 
    return merge(sort(node), sort(nextofmiddle));
}

任何帮助表示赞赏

最佳答案 你的排序程序看起来很棒.该错误似乎是您从排序例程返回的方式.如果您将您的排序称为就地排序,即

sort(head);
System.out.println(head);

旧头部未更新为sort()返回的新头部.注意在测试用例中显示的节点总是以旧头部开头的方式开头.如果未排序列表中的旧磁头恰好是排序列表中的新磁头,这似乎有效,如上一个示例所示.另一方面,如果在排序期间移动旧的头节点,则只能从旧头移动到的位置看到列表的其余部分.从列表前面到旧头的节点在超出范围时将被垃圾收集.

解决方法是将调用者列表的头部设置为sort()返回的头部,这是列表的新头部:

head = sort(head);
System.out.println(head);

这是您重新编写的代码,它会重现您的错误以说明问题:

class Main {
    public static void main(String[] args) {
        Node head = new Node(200, new Node(25, new Node(473, new Node(23, new Node(390, null)))));

        System.out.println("Example 1 (correct):");
        System.out.println(head);
        head = sort(head);
        System.out.println(head);

        head = new Node(200, new Node(25, new Node(473, new Node(23, new Node(390, null)))));

        System.out.println("\nExample 1 (incorrect):");
        System.out.println(head);
        sort(head);
        System.out.println(head);

        head = new Node(900, new Node(25, new Node(473, new Node(23, new Node(390, null)))));

        System.out.println("\n\nExample 2 (correct):");
        System.out.println(head);
        head = sort(head);
        System.out.println(head);

        head = new Node(900, new Node(25, new Node(473, new Node(23, new Node(390, null)))));

        System.out.println("\nExample 2 (incorrect):");
        System.out.println(head);
        sort(head);
        System.out.println(head);

        head = new Node(1, new Node(25, new Node(473, new Node(23, new Node(390, null)))));
        System.out.println("\n\nExample 3 (accidentally works, because the old head is still the new head):");
        System.out.println(head);
        sort(head);
        System.out.println(head);
    }

    static Node getMiddle(Node node) {
        Node fastptr = node.link; 
        Node slowptr = node; 

        while (fastptr != null) { 
            fastptr = fastptr.link; 

            if (fastptr != null) { 
                slowptr = slowptr.link;
                fastptr = fastptr.link; 
            }
        } 

        return slowptr; 
    }

    static Node merge(Node left, Node right) { 
        Node temp = new Node(-1, null);
        Node curr = temp;

        while (left != null && right != null) {
            if (left.data < right.data) {
                curr.link = left;
                left = left.link;
            }
            else {
                curr.link = right;
                right = right.link;
            }

            curr = curr.link;
        }

        curr.link = left == null ? right : left;
        return temp.link;
    }

    static Node sort(Node node) {
        if (node == null || node.link == null) {
            return node; 
        }

        Node middle = getMiddle(node);
        Node next = middle.link;
        middle.link = null;
        return merge(sort(node), sort(next));
    }
}

class Node {
    public int data;
    public Node link;

    public Node(int data, Node link) {
        this.data = data;
        this.link = link;
    }

    public String toString() {
        return this.data + (this.link != null ? "->" + this.link : "");
    }
}

输出:

Example 1 (correct):
200->25->473->23->390
23->25->200->390->473

Example 1 (incorrect):
200->25->473->23->390
200->390->473


Example 2 (correct):
900->25->473->23->390
23->25->390->473->900

Example 2 (incorrect):
900->25->473->23->390
900


Example 3 (accidentally works, because the old head is still the new head):
1->25->473->23->390
1->23->25->390->473

Try it!

点赞