【问题标题】:Check linkedlist circularity [closed]检查链表循环[关闭]
【发布时间】:2008-12-30 10:28:17
【问题描述】:

我需要一个将链表作为参数的方法,如果它是循环的,则返回真或假。

ex:circular linkedlist 表示存在指向任何先前节点的节点。 我忘了告诉一些限制,我不能使用任何数据结构或动态内存分配。 我只能使用局部变量,并且算法可以按照有人对我说的 n 步完成(我现在正在考虑使用两个指针?)

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    我相信您正在寻找Floyd's Cycle-Finding Algorithm。有一个比我在here 上给出的更好的解释。

    在 C 和 Scheme 中也有几个实现,文档超过 here

    【讨论】:

    • slownode 与 fastnode 的对比非常简单。聪明!
    • 第二个链接太棒了,谢谢分享。
    【解决方案2】:

    标准哈希计数适用:

    函数有循环(列表): foreach 列表中的节点: 地址 = address_of(node.next); 元素 = hashtable.get(地址); 如果(元素 == NULL): hashtable.put(地址) 别的: 返回真 返回假

    编辑:根据接受的答案的第二个链接,这可行但效率低下,这意味着有很多更有效的解决方案。

    【讨论】:

      【解决方案3】:

      这是微不足道的。

      previousnodes ← set()
      previousnodes.add(firstnode)
      currentnode ← firstnode.next
      while (currentnode in previousnodes) || (currentnode != null):
        previousnodes.add(currentnode)
        currentnode ← currentnode.next
      when (currentnode = 0) return false
      return true
      

      【讨论】:

      • 嗯,如果一个节点指向不是列表中第一个节点的前一个节点,这将不起作用。
      • 是的,这并不像我想象的那么简单。但实际上并非如此。 :)
      • Cheery:是的,这样更好。它可以工作,但需要 O(n) 内存空间。
      • 我知道,弗洛伊德的寻环算法比这个要好得多。这两者都不难。
      【解决方案4】:

      我自己遇到了一个解决这个问题的经典解决方案,忍不住把它贴在这里(虽然我猜原来的发帖人现在很可能已经毕业了)。从起始节点开始,只需开始反转列表。如果列表不是循环的,则该过程将以 Null 结束,如果列表确实是循环的,则该过程将在起始节点处结束。就是这样,一个具有恒定额外空间的线性时间算法。只需再次反转列表即可恢复原始列表。

      【讨论】:

      • 呸,Max 的第二个链接已经谈到了这个……
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-24
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 2018-07-22
      相关资源
      最近更新 更多