下面是使用本地引用逻辑创建链接列表的代码。
无法理解for循环内的代码,尤其是第二行。 (请参见// HERE
)
有人可以详细说明这种逻辑如何工作。
void push(struct Node** head_ref, int new_data)
{
struct Node *newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = new_data;
newNode->next = *head_ref;
*head_ref = newNode;
return;
}
struct Node* buildWithLocalRef()
{
int i=0;
struct Node *head = NULL;
struct Node **lastptrRef = &head;
for(i=1;i<6;i++)
{
push(lastptrRef,i);
lastptrRef = &((*lastptrRef)->next); // HERE
}
return head;
}
int main()
{
struct Node* head;
head = buildWithLocalRef();
printList(head);
return 0;
}
答案 0 :(得分:5)
您看到的技术是通过正向链接建立链接列表。这是从头到尾构建有序列表的最直接,最明智的方法,该列表没有尾指针(而您的指针没有尾指针)。
这里没有“参考”。这不是C ++。这是使用指向指针的指针。变量名被可怕地命名为btw。它是如何工作的:
head
是NULL
lastptrRef
的指针将始终保存要填充新的动态节点分配的下一个指针的地址(不是;存在区别)。最初,指向指针的指针保存着head
指针的地址,该地址最初为NULL
(很有意义,这就是您希望第一个节点挂起的位置)。push
中分配一个新节点。将该节点的next
指针设置为lastptrRef
所指向的指针中的任何值(在函数中作为head_ref
传递),然后lastptrRef
所指向的指针为更新为新的节点值。lastptrRef
赋予刚添加的节点中next
成员的地址,然后重复该过程。在每种情况下,lastptrRef
会在进入NULL
时保留包含push
的指针的地址。此push
函数使这一点很难理解。 (稍后会详细介绍)。直接进行正向链接很容易理解,在这种情况下,正向链接将使它变得非常容易理解
struct Node* buildWithLocalRef()
{
struct Node *head = NULL;
struct Node **pp = &head;
for (int i = 1; i < 6; i++)
{
*pp = malloc(sizeof **pp);
(*pp)->data = i;
pp = &(*pp)->next;
}
*pp = NULL;
return head;
}
在这里,pp
始终保存我们将使用新节点分配填充的下一个指针的地址。最初,它保存head
的地址。在插入每个节点时,pp
会被设置为插入的 latest 节点内next
指针的地址,从而使您能够在下一次迭代中继续执行链。循环完成后,pp
将next
指针的地址保存在列表的 last 节点中(或未插入head
的地址) ;请考虑如果将环路完全拉出会发生什么情况。我们希望它是NULL
来终止列表,所以执行最后的*pp = NULL;
。
您发布的代码执行相同的操作,但是以更复杂的方式进行,因为push
旨在将项目推入列表的 front (显然)。该函数始终将head_ref
指向的指针设置为添加的新节点,并且该节点的next
总是首先设置为*head_ref
中的旧值。因此,可以通过执行以下操作来构建 stack :
struct Node* buildStack()
{
struct Node *head = NULL;
for (int i = 1; i < 6; i++)
push(&head, i);
return head;
}
现在,如果您打印出结果后的链表,该数字将以相反的顺序输入。实际上,push
在这里名不虚传。双重目的来构建前向链表是很有创意的,我会同意的,但是最终它使它有些混乱。