【问题标题】:Slight confusion with linked lists in C与 C 中的链表略有混淆
【发布时间】:2010-11-11 11:42:52
【问题描述】:

我正在阅读有关linked lists and their implementation in C on Wikipedia 的信息。我没有像其他 C 概念那样快速掌握它们。

list_add() 函数中,我想知道为什么它说...

n->next = *p; /* the previous element (*p) now becomes the "next" element */

我真的不明白评论。为什么前一个元素会变成下一个元素?新节点不应该成为旧节点上的下一个吗?

请记住,我刚刚开始研究链表,所以请慢慢引导我。

谢谢。

更新

对不起,如果不是很明显,但我正在查看的所有代码都在 Wikipedia article 上。

【问题讨论】:

  • 你能提供一些程序的细节吗?
  • 可能是程序在现有节点之前添加了新节点
  • @Shweta Follow the link - 这就是我所看到的。
  • 你如何在 stackoverflow.com 上获得 21,500 分并且不懂链表?????
  • @PP 我是一名刚刚开始研究 C 的 Web 开发人员。因此,我所有的编程经验都是使用 JavaScript 和 PHP 等高级语言。此外,rep 并不表示编程能力 - 更多的是 你可以在这个网站上花费多长时间,并且看起来你知道你在说什么:P

标签: c linked-list


【解决方案1】:

因为列表是单链接的,这意味着它是A->B->C->etc,它必须遍历整个列表才能在末尾添加新元素。

相反,它会在开头添加新元素 n,并将 n->next 指向前一个第一个元素 p

【讨论】:

  • 方法 list_add 不一定要在开头添加新项目,它也可以将项目插入到列表的中间。该函数的注释清楚地说明了这一点。
  • 实际上,如果你传递一个不是第一个元素,你会改变链。想象一下,你有链 A->B-> 并且你插入 QB 作为传递的元素,你会得到两个链:A->B->CQ->B->C 因为你不能“返回”并改变 A->next
【解决方案2】:

在最简单的链表实现中,新节点被添加到链表的前面,因为这样更容易。您只需要一个指向列表第一个节点的指针,而无需搜索列表即可找到末尾。更复杂的实现可能会保留前端和结束指针,以便添加到列表的任一端。

【讨论】:

  • 函数前的注释说明:“参数:**p 是我们希望插入的节点。如果该节点为空,则将其插入开头”。所以list_add所做的插入不一定是在开头。
【解决方案3】:

这是因为该方法将新节点添加到列表的开始,即新创建的节点成为列表中新的第一个节点。

在列表开头添加新节点的一般方法:

// allocate new node pointed by new_node and fill it.

// make new node the first node by making it's next point to current head.
new_node->next = head; 

// head should always point to the beginning of the list.
head = new_node; 

【讨论】:

    【解决方案4】:

    list_add 函数不一定在列表的开头添加一个新节点——它只是添加一个位于p 之前的新节点。

    参数p 可以间接指向列表开头的节点,或列表中的任何其他节点。

    然后,此代码创建一个新节点,将其 next 字段设置为 p 指向的任何内容。

    更新:

    这段代码使用了一个指向节点的指针技巧,这在处理链表时非常有用。如果您是第一次看到链表,这可能会让人感到困惑。但是你应该花时间去理解它,因为它是指针强大功能的一个很好的例子。

    在代码中,p 指向一个指针,然后指针指向一个节点。这意味着p 可以间接指向列表中的第一个节点:

    ...这意味着add_node 将在列表的开头插入一个新节点。但是p也可以间接指向列表中的其他节点:

    在第二个示例中,add_node 将在列表的第一个和第二个节点之间插入一个新节点。

    【讨论】:

    • 不是真的:p 应该从任何节点指向一个 link。毕竟,指向节点的指针不是LLIST** 类型,它只是LLIST*
    • @Vlad:我不想通过进入指针对指针的事情来增加额外的混乱,但你是绝对正确的。我已经稍微编辑了这个答案以避免说错话。
    【解决方案5】:

    新节点被附加到现有列表的开头。

    [0] [1] [2] + [n] =[n] [0] [1] [2]

    【讨论】:

      【解决方案6】:

      list_add 函数将一个元素附加到列表的开头。所以这个注释意味着我们的新元素(n)必须指向列表的旧头(p):

      [p]->[1]->[2] + [n] ==> [n]->[p]->[1]->[2]

      如果我们要在列表末尾添加一个元素,新节点应该是旧节点的下一个:

      [0]->[1]->[p] + [n] ==> [0]->[1]->[p]->[n]

      【讨论】:

        【解决方案7】:

        函数list_add 得到p,它是指向链接的指针(也是指针),它指向我们需要在其前插入新数据的元素。 n是新分配的节点,所以n->next = *p;基本上是说“新节点的下一个链接设置为指向*p指向的节点”。

        ... [数据,下一个] >[数据,下一个] > >[数据,下一个] ... | | ^ | | | ---- | --- | | | [p] ------------------------ | [n] ------> [数据,下一个] | | | ---------------

        (我们正在设置最后一个链接,从 [n]->[...next] 开始)

        代码中的注释绝对令人困惑。更好的是“将新项目的下一个列表项设置为给定链接指向的项目”。这绝对是过于冗长了。

        【讨论】:

          【解决方案8】:

          因为您要将它添加到索引中,所以它会将“p”向上推一个节点,以便新节点可以插入前一个 p 的索引

          【讨论】:

            【解决方案9】:

            在链表中,您可以在任何地方添加新节点。 假设您想在链表的开头添加一个节点,您可以通过 n->next=start;//新节点的next指向第一个节点 start=n;//新节点成为第一个节点 您遇到问题的方式是在给定节点之前添加一个新节点

            【讨论】:

              猜你喜欢
              • 2016-03-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-07-07
              • 2021-04-07
              • 2016-06-27
              • 1970-01-01
              • 2016-06-28
              相关资源
              最近更新 更多