【问题标题】:traversing a singly linked list in C++在 C++ 中遍历单链表
【发布时间】:2009-10-05 22:54:20
【问题描述】:

我想知道是否可以像这样遍历链表:


currentNode = randomNode;//where randomNode may or may not = firstNode
prevNode = firstNode;
while(prevNode != currentNode && prevNode->link != currentNode)
{
    prevNode = prevNode->link;
}

当我试图在单链表中查找 currentNode 之前的节点时,是否可以在 C++ 中执行此操作?

我试图在一个控制台应用程序中为学校作业实现类似的东西,所以假设我不能使用任何花哨的东西,比如 boost 库/列表/任何让生活更轻松的东西等等。所以基本上,我只有相当原始数据类型和库供我使用。

【问题讨论】:

  • 为什么“想知道”如果你可以尝试一下,看看它是如何(以及是否)工作的?我在这里看不到任何问题,假设您始终至少有一个节点,并且randomNode 保证是列表中的一个有效节点(因此您永远不会“跑到最后”)。
  • 您到底想做什么?在链表中搜索节点?
  • while 条件看起来有点奇怪...为什么要测试 prevNode != currentNode ?另外,列表可以为空吗?会不会出现 currentNode 不在列表中的情况?
  • @Pavel:它已经在我的代码中,但我还没有在一个可以轻松测试的地方。我想我会在这里检查一下它是否合乎逻辑,并且至少有可能我真正的核心问题是,就 prevNode = prevNode->link; 去。 @Ashwin:我想你可以称之为搜索,但我计划使用这个循环来帮助我在两个节点之间插入一个新节点。 @Jim:我正在测试 randomNode 是否等于 firdtNode 在这种情况下之前没有节点。

标签: c++ pointers linked-list singly-linked-list


【解决方案1】:

您可能需要确保 prevNode->link 也不是空引用,以防 currentNode 实际未链接。

【讨论】:

  • 如果 currentNode 保证在列表中(从描述来看似乎是),循环将始终在列表末尾之前终止。
【解决方案2】:

这应该可以正常工作。你试过了吗?

【讨论】:

  • 是和不是。它在我的代码中,但缺少其他部分,而且我已经有几天没有处理它了,所以并不是所有的东西都“挂钩”了
【解决方案3】:

该代码将遍历列表的某些部分,但哪一部分取决于列表的链接方式。如果它从头->尾(阅读:头节点链接到指向尾的节点),那么您将从随机位置开始遍历您的列表到尾。如果链接是 head

以上所有内容都假设有一些链接列表:

[head]<->[0...N Nodes]<->[Tail]

链接可以是任何一种方式。

此外,您可以链接头节点和尾节点并创建循环链表。在这种情况下,可以通过简单地遍历直到回到原始节点来访问所有节点。

【讨论】:

    【解决方案4】:

    确保考虑所有可能的边缘情况:

    • randomNode 等于 firstNode 会发生什么?你回什么? 应该返回什么?
    • 当randomNode 是列表中的最后一个节点时会发生什么?
    • 当randomNode 是NULL 时会发生什么?
    • randomNode 不在列表中时会发生什么?

    现在,并非所有这些情况都适用,这取决于您是否了解randomNode,其中一些可能是微不足道的。但都值得思考。

    如果您仔细考虑所有这些问题,那么有一个简单而优雅的解决方案可以处理所有这些问题。

    【讨论】:

      【解决方案5】:

      代码看起来不错,但我建议对您的 while 条件稍作更改

      while(prevNode != currentNode && prevNode != NULL)
      

      有两个原因

      • 如当前所述,如果我们正在寻找的节点被prevNode 或prevNode-&gt;link 指向,您的代码可能会停止(因此我们将不知道这两个点中的哪一个指向currentNode -- 如果我们想知道,我们必须检查if 条件)。通过上述更改,保证目标节点存储在prevNode 中(如果有的话——请参阅下一点)。
      • 为了安全起见,最好检查一下prevNode 不是NULL。但是,正如 Pavel 所提到的,如果保证 currentNode 在列表中,则无需进行此测试。

      根据评论进行编辑

      鉴于您不需要知道currentNode 是在prevNode 还是prevNode-&gt;link,并且由于您想(如果可能)在currentNode == prevNode-&gt;link 上停止,那么您原来的while 就可以了。不过……

      上面有一个 if 语句 阻止的代码 prevNode 从为空 已经

      您似乎忽略了为什么要检查NULL。是的,你之前检查一下很好,但是我们在循环中检查 NULL 的原因是currentNode 在列表中不是,所以你最终到达了最后一个节点。大概(如果您像大多数其他链表一样这样做)您最后一个节点的link 的值是NULL。如果是这样,您当前的代码最终将调用NULL-&gt;link,这当然会使您的程序崩溃。这就是为什么你仍然应该检查NULL

      while(prevNode != NULL && prevNode != currentNode && prevNode->link!=currentNode)
      

      如果您绝对确定currentNode 将在列表中,那么我猜检查也是不必要的,但这确实是一个好习惯进入。

      【讨论】:

      • 我之所以有这样的条件是因为代码中有一个 if 语句阻止 prevNode 已经为空,所以基本上我想确保 prevNode 等于当前节点或 currentNode 之前的节点,哪个是第一个。
      【解决方案6】:

      你甚至可以拥有:

      while (prevNode && prevNode != currentNode)
          prevNode = prevNode->link;
      

      但是你的看起来不错。

      【讨论】:

        【解决方案7】:

        我会用发布的代码更改的一件小事(除了在其他答案中讨论的如果 currentNode 不在列表中或其他错误处理中运行列表末尾的可能性之外)是当 while循环完成你不知道prevNode 或prevNode-&gt;link 是否指向currentNode。这不是一个大问题(因为您可以轻松测试它),但在我看来最好在搜索之前测试这种特殊情况,因此很明显这是一个特殊情况。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-07-01
          • 1970-01-01
          • 2013-07-28
          • 2018-11-23
          • 1970-01-01
          • 1970-01-01
          • 2018-03-27
          • 2012-08-08
          相关资源
          最近更新 更多