您无法消除“先前”变量,但可以伪装它;此外,您可以构造循环,使其成为唯一的迭代变量。
当然要插入新的,您需要更新前一个节点以指向它。
您可以通过在列表中向前查看并处理各种情况来从当前节点执行此操作。
另一种方法是在前一个节点中保留指向指针字段的指针。
node **ppnode;
for (ppnode = &head;
*ppnode != NULL && (*ppnode)->value >= newnode->value;
ppnode = &(*ppnode)->next)
; /* empty body */
newnode->next = (*ppnode) ? (*ppnode)->next : NULL;
*ppnode = newnode;
在这里,current
我们不使用指向当前节点的ppnode
指针,而是使用间接指向当前节点的指针。它不是指向该节点,而是指向指向该节点的指针(因此必须适当地键入:它是指向指针的指针:双星)。
指向第一个节点的指针是列表head
变量,因此最初ppnode
指向该head
变量。之后指向每个其他节点的指针是next
前一个节点的字段:这些字段中的每一个next
都非常像head
列表其余部分的一个。因此,使用这个ppnode
变量,我们跟踪必须更新的前一个节点中的位置,而不跟踪前一个节点本身。这让我们可以处理没有前一个节点的列表前面的情况。
让我们追踪为空的情况head
(列表为空)。
ppnode
指向head
. 但是*ppnode
为空,因此循环体永远不会执行。
由于ppnode
指向head
,这些行:
newnode->next = (*ppnode) ? (*ppnode)->next : NULL;
*ppnode = newnode;
含义相同:
newnode->next = head ? head->next : NULL;
head = newnode;
这些行中的条件检查处理将新节点添加到空列表或非空列表尾部的情况。如果列表为空或其中的所有值都小于新值,则循环以ppnode
指向列表的空终止符(head
如果列表为空,否则next
为尾节点的字段)终止。由于*ppnode
为空,我们不能服从(*ppnode)->next
。没有下一个;新节点是最后一个节点,它next
必须为空。
现在让我们看看在有头节点的情况下会发生什么,并且它的值更大,因此必须将新节点插入到最前面。在这种情况下ppnode
指向head
,和以前一样,并且*ppnode != NULL
条件为真。但是(*ppnode)->value >= newnode->value
条件失败,因此循环永远不会执行。
现在,我们再次执行此代码的等价物:
newnode->next = head ? head->next : NULL;
head = newnode;
但这一次head
不是空的,所以newnode->next = head->next
, 和以前一样,newnode
变成了新的head
。
所有其他情况都从这两个开始:除了不是head
,动作使用next
前一个节点的指针来执行,这就像列表其余部分的头部。