算法:合并排序与链接列表缺失项目

时间:2018-04-21 14:43:22

标签: java algorithm sorting

我正在尝试使用合并排序对链接列表进行排序。该列表实际上已经排序,但它有点缺少第一个项目。

合并排序功能:

public Node mergeSort(Node head) {
    if (head == null || head.next == null) {
        return head;
    }

    Node middle = middleElement(head);
    Node nextofMiddle = middle.next;
    middle.next = null;
    return merge(mergeSort(head), mergeSort(nextofMiddle));
}

public Node merge(Node left, Node right) {

    Node temp = new Node();
    Node newHead = temp;
    while (left != null && right != null) {
        if (left.info <= right.info) {
            temp.next = left;
            temp = left;
            left = temp.next;
        } else {
            temp.next = right;
            temp = right;
            right = temp.next;
        }
    }
    temp.next = (left == null) ? right : left;
    return newHead;
}

public Node middleElement(Node head) {
    if (head == null) {
        return head;
    }
    Node slow = head;
    Node fast = head;
    while (fast.next != null && fast.next.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

所以我使用遍历将列表打印到屏幕:

    public static void main(String[] args) {
    MyLinkedList mll = new MyLinkedList();

    mll.insert(3);
    mll.insert(5);
    mll.insert(9);
    mll.insert(1);
    mll.insert(8);
    mll.insert(7);
    mll.insert(2);



    mll.mergeSort(mll.head);
    mll.traverse();

}

我有这样的结果: 1 and 2 missing!

检查后,我注意到链表值的“尾部”仍为2.我不知道为什么有人可以帮忙?我真的很喜欢编程,对于给您带来的任何不便表示歉意。谢谢你的阅读!

2 个答案:

答案 0 :(得分:0)

我可以看到几个问题。 @rcgldr在评论中提到的一个是merge方法正在返回临时节点newHead,但该节点没有值,并且不是图形的一部分。你需要归还它的孩子newHead.next

另一个问题是你永远不会重置列表的头部。因此,在所有排序之后,mll的头部仍然指向原始头部,在这种情况下是3。因此,当您遍历列表时,您会跳过12。我不确定你的链表类是什么样的,但是这样的东西应该是关闭的 - 只需将mergeSort返回的最终节点分配给列表的头部。然后,当你遍历时,你应该从正确的位置出发:

    mll.head = mll.mergeSort(mll.head);
    mll.traverse();

答案 1 :(得分:0)

你离正确的解决方案不远。我通过添加1行并更改3来获得工作排序。

您的合并没有按照您的想法进行。

分配假头节点(你称之为temp,而不是一个好的名称选择;尝试falseHead)是一个好主意。那么falseHead.next就是真正的头脑。这就是你最终将作为排序列表返回的内容。请注意,最初它是null,这是您所期望的。

您缺少的是变量tail,用于引用合并列表中的当前 last 节点。由于最初根本没有最后一个节点,因此应将其初始化为falseHead。因此,当您通过设置tail将第一个元素附加到当前结果的tail.next时,您还将设置falseHead.next,即创建头元素。一切顺利。

现在,删除right列表的当前头并将其附加到合并结果的逻辑是什么?这只是3个步骤:

  1. 通过tail.next right的当前负责人来执行追加操作。
  2. tail更新为tail.next
  3. right更新为right,删除right.next的头部。
  4. 当然左侧是相似的。

    祝你好运。你很亲密。