代码说明(链表C)

这不是我的代码。 我把这个代码从这个网站上删除了:

http://www.macs.hw.ac.uk/~rjp/Coursewww/Cwww/linklist.html

我正在使用有关如何构建链接列表的参考资料。 我对发生的事情感到有点困惑。 有人可以向我解释发生了什么事。 我会用1-5来标记令我困惑的事情。

#include #include struct list_el { int val; struct list_el * next; }; typedef struct list_el item; void main() { item * curr, * head; int i; head = NULL; //1 for(i=1;ival = i; curr->next = head; //2 head = curr; //3 } curr = head; // 4 while(curr) { //5 printf("%d\n", curr->val); curr = curr->next ; } 
  1. head = NULL→为什么head被设置为NULL? 我知道你应该(我是出于习惯),但我不知道为什么。

  2. curr-> next = head→我也从未真正理解过这一点。 也许我对“head”的定义有误,但在常规链表中,是列表的起始节点还是最后一个节点? 我一直认为它是起始节点,但在这一行中,它看起来像是最后一个节点。

  3. head = curr→为什么我们将它设置为curr?

  4. curr = head→然后在循环完成后设置curr = head。

  5. while(curr)→只是为了确保,这是遍历列表,它等同于while(curr!= NULL)对吗?

#1: head = NULL

初始化指针通常建议在声明时将指针初始化为NULL(1)或在声明后立即将指针初始化为(2)。 如果程序员错误地取消引用未初始化的指针,则返回垃圾值。 如果静态分析器和编译器没有显示未初始化指针的警告或错误消息,通常很难调试。

有关更多信息,请参阅Steve McConnell的代码完成:软件构建实用手册防御性编程的维基百科页面。

#2: curr->next = head

构建链表curr节点与序列中先前创建的节点“链接”。

#3: head = curr

更新头指针。 head指针正在更新以指向最近的malloc ed节点。

下面的插图可视化步骤#2和#3:

第一第二第三排在最后

#4: curr = head

重新初始化指针。 此步骤类似于步骤#2: curr->next = head 。 通过将curr节点设置为headcurrwhile循环中的链表遍历“准备好”。 从类比来看,它就像在循环开始时将迭代变量初始化为0(即i = 0 )。 要显示此步骤,请参阅下面显示执行此语句之前/之后的插图:

之前

后

#5: while(curr)

遍历清单。 鉴于curr指向第一个节点(来自步骤#4),此while循环遍历列表,直到curr->next返回NULL。 在一个不太抽象的forms中,我们可以将此语句重写为while(curr != NULL)

  1. 头指向列表的头部。 由于列表当前为空,因此将其设置为null
  2. 将节点添加到列表时,将“next”指针设置为列表的当前头部。 将新节点放在列表的头部。
  3. 将“head”设置为“curr”以使新节点成为列表的头部。
  4. 循环结束后,您将重新使用“curr”变量遍历列表。
  5. 您将依次通过列表设置“curr”到每个节点,直到您离开列表的底部(其中curr-> next为null)

(1)。 你需要将它设置为某种东西,使用NULL是一种说它不指向任何东西的方式。 通常NULL与0相同。在某些语言中,您不需要初始化变量,因为它会自动将其设置为nil。 但是C不这样做所以你必须自己做。

(2)。 head指向列表的第一个节点。 首先,它是NULL,这意味着列表是空的,因此不指向任何东西。 cur是一个想要插入列表的新节点。 curr->next想要指向现有列表的第一个节点,这就是为什么curr->next设置为head

(3)。 此时, head不再指向第一个节点。 第一次通过循环,它看起来像这样:

 CURR  - >节点1  - > NULL
         头 -  ^

但总的来说它看起来像这样

 CURR  - >节点3  - >节点2  - >节点1  - > NULL
          头 -  ^

所以我们需要更新head到点第一个节点。 由于curr指向新创建的节点,它位于前面,我们只需设置指向与curr相同的节点。

(4)。 该计划的第一部分已经完成。 不再需要curr ,因为它用于跟踪我们创建的新节点。 这是一个临时变量。 这行curr = head意味着我们要将curr初始化到列表的开头。 我们可以使用另一个变量来使其更具可读性,但您通常会看到临时变量的重用。

(5)。 对。 您可能会看到NULL定义为(void*)0 ,因此它与0相同。除了60年代或70年代的旧机器外,您可能永远不会看到0以外的其他值。 从逻辑上讲,它相当于: while (curr != 0)while (curr)相同。

1. head = NULL→为什么head被设置为NULL?
初始化变量是一种很好的做法。 在一些系统中,声明的变量具有在抓取地址空间时在内存中发生的任何事情。

2. curr-> next = head→我也从未真正理解过这一点。 也许我对“head”的定义有误,但在常规链表中,是列表的起始节点还是最后一个节点? 我一直认为它是起始节点,但在这一行中,它看起来像是最后一个节点。
是的,头部是起始节点。

3. head = curr→为什么我们将它设置为curr?
此循环在此处添加新节点作为头部。 像堆栈一样。 其他方法可以在尾部添加新节点。 两种方式仍然是“链表”。

4. curr = head→然后在循环完成后设置curr = head。
curr就像一个索引,一个工作变量,因此你不会破坏数据结构。 他完成后重置了它。 如果愿意的话,“重绕磁带”。

5. while(curr)→只是为了确保,这是遍历列表,它等同于while(curr!= NULL)对吗?
是的,这是你在C中找到的那些隐含的东西之一。在while循环中,任何东西都是隐含的, while(whatnot != 0)和null == 0。

首先,您可以在链接列表头始终为空和简单C ++链接列表中找到为什么head始终为NULL的问题的答案。 初学者教程,您可以在c中找到单链表 。 语句head = curr将指针头的值与通过分配内存接收非零值的当前指针的值的NULL相关联。 while(curr)是一个循环,当long curr与NULL不同时运行,NULL作为指向地址的宏关联零值。

我们什么都没有开始。 那是什么

 head = NULL; 

告诉我们。 我们还没有列表,所以我们无法访问它。

现在我们从1到10循环。我们从后到前构建一个列表。 HEAD为NULL,因此“last”(第一次创建)指向NULL:

 curr->next = head; // head is NULL in the first loop 

HEAD现在设置为这个新元素:

 head = curr; 

第二个遍历此循环,head将指针存储到最后创建的项目。 然后新创建的将指向它。 我们在最后一项前面设置了这个新项目。

设置

 head = curr; 

需要完成,以确保头部在下一个循环中包含正确的指针。 它被称为head,因为它始终存储在此之前创建的列表的开头。

// 4不是必需的。

之前的最后一次操作是:

 head = curr; 

所以

 curr = head; 

没有意义。

第五个遍历列表。 “curr”指向第一个项目(带有非NULL地址),并在每个循环中设置为curr-> next。 一旦curr为NULL(在最后一项),该语句就不再为真。

在第4个问题中,我不认为curr=head是必要的。因为当循环结束时,curr和head指针指向同一个节点(i = 10的节点)。 但这是个好习惯。