代码说明(链表C)

时间:2013-03-15 20:42:00

标签: c linked-list head

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

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

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

#include<stdlib.h>
#include<stdio.h>

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;i<=10;i++) {
      curr = (item *)malloc(sizeof(item));
      curr->val = 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-&gt; next = head→我也从未真正理解过这一点。也许我对“head”的定义错了,但是在常规链表中,它是列表中的起始节点还是最后一个节点?我一直认为它是起始节点,但在这一行中它看起来像是最后一个节点。

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

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

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

7 个答案:

答案 0 :(得分:19)

  

#1:head = NULL

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

有关详情,请参阅Steve McConnell's Code Complete: A Practical Handbook of Software Construction上的Defensive Programming或维基百科页面。

  

#2:curr->next = head

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

  

#3:head = curr

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

下图说明了步骤#2和#3:

first second third forth and final

  

#4:curr = head

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

before

after

  

#5:while(curr)

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

答案 1 :(得分:5)

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

答案 2 :(得分:3)

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

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

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

curr-->node1-->NULL
         head--^

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

curr-->node3-->node2-->node1-->NULL
          head--^

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

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

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

答案 3 :(得分:2)

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

<强> 2。 curr-&gt; 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。

答案 4 :(得分:2)

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

答案 5 :(得分:2)

我们从没有开始。那就是

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-&gt; next。一旦curr为NULL(在最后一项),语句就不再成立。

答案 6 :(得分:0)

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