关于如何检测链表中的循环,我看到了很多问题,但是我想了解为什么我们要这样做,换句话说,检测链表中的循环的实际用例是什么< / p>
答案 0 :(得分:4)
在现实生活中,您可能永远不需要检测链表中的循环,但是执行该操作的算法很重要,我在现实生活中已经多次使用它们。
例如,在通常情况下,当我假设它是树形时,我会递归地处理它。但是,如果它不是树形的并且具有循环,则将导致无限递归和堆栈溢出,因此我想在它爆炸之前抓住它。我通常使用Brent的循环查找算法,因为它很容易适应我的递归处理,并且开销极低。
周期查找算法在Pollard的“ rho”分解算法(https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm)中也很有用
学习这些算法时所学的思想也将在以后学习其他更复杂的事物时有用。
ETA:
我应该补充说,错误地产生循环的常见情况是用户专门创建链接的情况。例如,在Java中,一个类可以具有一个超类,例如,程序员编写class C extends A {}
。 extends
关键字在类之间创建链接。如果他还写class A extends C
,则说明他已经创建了一个循环,编译器必须检测到这种情况。
答案 1 :(得分:0)
带循环的链表没有结尾,链表包含两个到某个节点的链接 遍历链接列表将多次产生循环中的所有节点具有循环的格式错误(具有未知循环)的链接列表会导致列表迭代失败,因为迭代永远不会到达列表的末尾。因此,希望能够在尝试迭代之前检测到链表具有循环
您可以在这里找到答案
答案 2 :(得分:0)
因为,如果有这样的列表(例如):
head -> A -> B -> C -+
^ |
+-------+
和遍历它的代码如下:
node = head
while node <> null:
processNode(node)
node = node.next
那么您将从不完成循环。它会愉快地处理A, B, C, B, C, B, C,...
直到永远(或者直到宇宙热死为止,以先到者为准)。
一个普通的链表永远不会在其中循环。为了检测这样的简并列表,您可以查看this answer。
请注意,某些循环链接列表确实有效。我看到的一个示例是一个用于调度头部和尾部不相关的流程列表(因为处理它们的东西想要永久地遍历它们)。因此,调度程序将类似于:
curr = somePointInList()
while true:
runForABit(curr)
curr = curr.next