因此,我正在尝试对该链接列表进行排序,我理解代码mergeSort
的第9行下除这一点之外的代码的每一部分。
为什么必须将middle.next
设置为null
?我看不出这有什么必要吗?
这是我从中获取代码的链接(在Java示例代码下):
https://www.geeksforgeeks.org/merge-sort-for-linked-list/
代码如下:
// Java program to illustrate merge sorted
// of linkedList
public class linkedList {
node head = null;
// node a, b;
static class node {
int val;
node next;
public node(int val) {
this.val = val;
}
}
node sortedMerge(node a, node b) {
node result = null;
/* Base cases */
if (a == null)
return b;
if (b == null)
return a;
/* Pick either a or b, and recur */
if (a.val <= b.val) {
result = a;
result.next = sortedMerge(a.next, b);
} else {
result = b;
result.next = sortedMerge(a, b.next);
}
return result;
}
node mergeSort(node h) {
// Base case : if head is null
if (h == null || h.next == null) {
return h;
}
// get the middle of the list
node middle = getMiddle(h);
node nextofmiddle = middle.next;
// set the next of middle node to null
middle.next = null;
// Apply mergeSort on left list
node left = mergeSort(h);
// Apply mergeSort on right list
node right = mergeSort(nextofmiddle);
// Merge the left and right lists
node sortedlist = sortedMerge(left, right);
return sortedlist;
}
// Utility function to get the middle of the linked list
node getMiddle(node h) {
// Base case
if (h == null)
return h;
node fastptr = h.next;
node slowptr = h;
// Move fastptr by two and slow ptr by one
// Finally slowptr will point to middle node
while (fastptr != null) {
fastptr = fastptr.next;
if (fastptr != null) {
slowptr = slowptr.next;
fastptr = fastptr.next;
}
}
return slowptr;
}
void push(int new_data) {
/* allocate node */
node new_node = new node(new_data);
/* link the old list off the new node */
new_node.next = head;
/* move the head to point to the new node */
head = new_node;
}
// Utility function to print the linked list
void printList(node headref) {
while (headref != null) {
System.out.print(headref.val + " ");
headref = headref.next;
}
}
public static void main(String[] args) {
linkedList li = new linkedList();
/*
* Let us create a unsorted linked list to test the functions
* created. The list shall be a: 2->3->20->5->10->15
*/
li.push(15);
li.push(10);
li.push(5);
li.push(20);
li.push(3);
li.push(2);
// Apply merge Sort
li.head = li.mergeSort(li.head);
System.out.print("\n Sorted Linked List is: \n");
li.printList(li.head);
}
}
// This code is contributed by Rishabh Mahrsee
答案 0 :(得分:0)
因此,如果您看到完整的代码,将mergeSort()
递归调用,
// Apply mergeSort on left list
node left = mergeSort(h);
// Apply mergeSort on right list
node right = mergeSort(nextofmiddle);
通过放置middle.next = null
,实际上破坏了方法堆栈中调用方法的递归。因此,当我们递归调用相同的方法
if (h == null || h.next == null) {
return h;
}
因此,如果您看到psedo代码,
MergeSort(headRef)
1) If the head is NULL or there is only one element in the Linked List
then return.
2) Else divide the linked list into two halves.
FrontBackSplit(head, &a, &b); /* a and b are two halves */
3) Sort the two halves a and b.
MergeSort(a);
MergeSort(b);
4) Merge the sorted a and b (using SortedMerge() discussed here)
and update the head pointer using headRef.
*headRef = SortedMerge(a, b);
它有效地将列表分为两半,并通过调用相同的方法将它们单独合并。为了达到相同的目的,首先要复制nextofmiddle
中的下一个值,然后使它们middle.next = null;
中断递归循环。
我希望这可以澄清您的疑问。
答案 1 :(得分:0)
因此,看来作者正在方法node getMiddle(node h)
中寻找列表的中间点。这将返回中间节点,但是您要将列表分为两部分,左侧和右侧。
设置middle.next = null
会将列表分为两部分。
答案 2 :(得分:0)
将列表分成两部分:找到中间元素时,第一部分将在中间元素结尾,因此middle.next
设置为null。 middle.next
的先前值是第二部分的开始。
答案 3 :(得分:0)
mergeSort
将中间节点的next
成员设置为null
,以将列表h
分为2个单独的列表h
和nextofmiddle
它通过递归调用自身进行排序,然后合并以生成sortedList
。
但是请注意,此代码有一个主要问题:方法sortedMerge
也是递归的,其堆栈深度为两个列表的组合长度,可能很大。编译器无法轻松地将这种递归简化为尾递归,因此使用此代码对长列表进行排序很可能会崩溃。
答案 4 :(得分:0)
middle.next = null
的目的是将列表分为两部分。链表中最后一个节点之后的值应始终为NULL,这就是为什么作者将next
节点的middle
节点设置为NULL的原因。作者正在创建一个包含从head
到middle
的节点的子列表,以及另一个包含从nextofmiddle
到列表末尾的节点的子列表。每次调用此函数时,子列表都会分解为较小的部分,这是合并排序过程的一部分。