我正在尝试使用合并排序对链接列表进行排序。该列表实际上已经排序,但它有点缺少第一个项目。
合并排序功能:
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.我不知道为什么有人可以帮忙?我真的很喜欢编程,对于给您带来的任何不便表示歉意。谢谢你的阅读!
答案 0 :(得分:0)
我可以看到几个问题。 @rcgldr在评论中提到的一个是merge
方法正在返回临时节点newHead
,但该节点没有值,并且不是图形的一部分。你需要归还它的孩子newHead.next
。
另一个问题是你永远不会重置列表的头部。因此,在所有排序之后,mll
的头部仍然指向原始头部,在这种情况下是3
。因此,当您遍历列表时,您会跳过1
和2
。我不确定你的链表类是什么样的,但是这样的东西应该是关闭的 - 只需将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个步骤:
tail.next
right
的当前负责人来执行追加操作。tail
更新为tail.next
。right
更新为right
,删除right.next
的头部。当然左侧是相似的。
祝你好运。你很亲密。