从一开始:您有两个列表和一个新的列表头,您将返回它们。pnext 最初指出了这一点。
该代码旨在尽可能少地重新分配指针,因此尝试保持输入列表的初始“下一个”指针完好无损。
list1 pnext->list->Null
|
V
o->o->o...
list2
|
V
o->o->o...
交换是为了确保较小的元素是 list1 的第一个元素。这些行的作用是:
一步一步来:
*pnext = list1;
获取 *pnext(它是第一次迭代之前的列表)以指向包含最小元素的节点:
list1
|
V
o->o->o...
^
|
list<-pnext
list2
|
V
o->o->o...
.
pnext = &list1->next;
是棘手的部分,如前所述, & 运算符的优先级较低。它也很难以图形方式显示,因为它实际上是查看 Node 构造的一部分。像这样的东西:
list1
|
V
o---->o->o...
^ ^
| |
list x<-pnext
list2
|
V
o->o->o...
其中 x 是 list1 指向的 o 的下一个指针。
list1 = *pnext;
推进 list1 头,因为它的第一个元素被处理。
list1<-pnext
|
V
o->o->o->...
^
|
list
list2
|
V
o->o->o->...
从这里开始,您与列表无关,因为您想将其作为合并列表的头部返回。
不变量 pnext 指向最后处理元素的 next 指向的位置,这是 list1-2 中最小元素应该去的位置。有趣的事情发生在交换中,尝试自己制定确切的程序(很难像这样画,并且很好的练习来理解 ** 做了什么)。如果我找到一个好的方法来绘制它,我可能会添加它。
你不能使用list = list-> next;
它会做这样的事情:
list1
|
V
o->o->o->...
^
|
list
list2
|
V
o->o->o->...
这意味着你会失去那个孤独的 o(以及随着循环的进行而最终失去的一切)。
编辑:*pnext = list2;
最后这样做:
循环终止(上述语句之前的状态):
list1<-pnext
|
V
o->o->o->null
^
|
list
o->o->o->...
^
|
list2
声明后:
list1
|
V
o->o->o Null
^ |
| |
list |
V
o->o->o->...
^
|
list2<-pnext
该语句将剩余的列表附加到列表的末尾。然后返回 Node* 列表,指向合并列表的头部。
编辑2:
一路走来,pnext 会更好地表示为:
list1
|
V
o->o->o Null
^ |
| |<-pnext
list |
V
o->o->o->...
^
|
list2
这意味着它指向最后处理节点的下一个指针。