Algorithm 循环列表是否总是由一个适当的列表(以nil结尾)和一个循环来模拟?

Algorithm 循环列表是否总是由一个适当的列表(以nil结尾)和一个循环来模拟?,algorithm,data-structures,linked-list,circular-list,Algorithm,Data Structures,Linked List,Circular List,我的直觉是,一个循环列表可以通过一个适当的列表(带有结束标记)和一个循环反复遍历整个列表来模拟。我的感觉是,循环列表更干净,因为控制逻辑(循环)内置于结构中。另一方面,将控制逻辑从结构中分离似乎是一种关注点分离,这在某些情况下可能是有利的。我不太确定的是,在什么情况下,每种方法都是有用的。此外,我不太确定模拟是否总是可能的。如果没有,你能举个反例吗?是的,这总是可能的 优点: 你有一个循环列表。这大概是个职业选手,否则你就不会这么做了 缺点: 出于某种原因,您浪费了时间在普通列表周围实现包

我的直觉是,一个循环列表可以通过一个适当的列表(带有结束标记)和一个循环反复遍历整个列表来模拟。我的感觉是,循环列表更干净,因为控制逻辑(循环)内置于结构中。另一方面,将控制逻辑从结构中分离似乎是一种关注点分离,这在某些情况下可能是有利的。我不太确定的是,在什么情况下,每种方法都是有用的。此外,我不太确定模拟是否总是可能的。如果没有,你能举个反例吗?

是的,这总是可能的

优点:

  • 你有一个循环列表。这大概是个职业选手,否则你就不会这么做了
缺点:

  • 出于某种原因,您浪费了时间在普通列表周围实现包装器,而不是一开始就编写循环列表

FWIW,我多年前就得出结论,所有清单都应该是循环的。这允许您使用单个指针指向列表中的最后一个元素(概念上的),但您可以在O(1)时间内轻松地在列表的开头和结尾插入。此外,使列表循环可以减少列表操作代码中特殊情况的数量(在下一个指针处总是有一个有效节点)。

是的,这总是可能的

优点:

  • 你有一个循环列表。这大概是个职业选手,否则你就不会这么做了
缺点:

  • 出于某种原因,您浪费了时间在普通列表周围实现包装器,而不是一开始就编写循环列表

FWIW,我多年前就得出结论,所有清单都应该是循环的。这允许您使用单个指针指向列表中的最后一个元素(概念上的),但您可以在O(1)时间内轻松地在列表的开头和结尾插入。此外,使列表循环可以减少列表操作代码中特殊情况的数量(在下一个指针处总是有一个有效节点)。

是的,您可以模拟它。但是您应该需要两个指针来控制列表。 一个指针用于访问当前元素,一个指针用于保存第一个元素。
您必须制定一些逻辑来检测“当前元素指针”何时超出列表边界,并将其移动到第一个元素。

是的,您可以模拟它。但是您应该需要两个指针来控制列表。 一个指针用于访问当前元素,一个指针用于保存第一个元素。
您必须制定一些逻辑来检测“当前元素指针”何时超出列表的边界,并将其移动到第一个元素。

是。为什么不清楚?你为什么不列出你认为有哪些优点和缺点?(如果没有这一点,人们会认为你没有做好功课,你可能会得到更多“接近”的回答)你所说的“带循环的正常列表”到底是什么意思?什么是带循环的“正常”列表?或者你所说的模拟是什么意思?清单就是清单。我认为定义很简单。没有模拟,是的。为什么不清楚?你为什么不列出你认为有哪些优点和缺点?(如果没有这一点,人们会认为你没有做好功课,你可能会得到更多“接近”的回答)你所说的“带循环的正常列表”到底是什么意思?什么是带循环的“正常”列表?或者你所说的模拟是什么意思?清单就是清单。我认为定义很简单。没有模拟,我看不出有什么真正的区别。您可以将特殊的
null
元素与
null
指针进行比较,或者检查下一个元素是否为
,以检测结束。这是一个实现细节,我个人看不出两者之间有什么优势。此外,如果列表是单链接的,则不能在O(1)的末尾插入元素,除非每个列表存储一个额外的指针,即使它是循环的。@luk32如果它是单链接的,并且是循环的,则绝对可以在O(1)的末尾插入元素;您只需要记住,指向列表的指针指向尾部,而不是头部。循环性的好处对于双链表来说特别高,因为它简化了链接维护代码。好吧,这是一种欺骗。如果指针指向尾部,那么如何定义列表中的顺序?您要么重新定义(或重新解释)列表,要么让检索第一个元素花费
O(n)
时间。但我仍然看不到循环是如何简化维护代码的。你总是有特殊情况。你能说得更具体些吗?我给出了3个选项,都是检测列表末尾的特例,还有其他的吗。更通用?@luk32否,第一个元素可在
tail->next
(即O(1));我可能应该说“最后一个元素”,因为“尾巴”这个词有时会有些混淆。对于双链接列表,最大的好处是插入或删除元素;如果
next
prev
指针可能是
NULL
,您必须先检查它们,然后再间接通过它们来修复
next->prev
/
prev->next
,而如果列表是循环的,您就不需要了。哦,我现在明白了。我没有看到
head
tail->next
,因此您可以在
O(1)
中同时获得tail和head。简化的插入/删除也很有意义。而且你不会损失任何东西,当你想要实现“开放式”列表时,因为我所说的,总是有特殊情况来检测结束。因此,实际上做与OP要求相反的事情是很有意义的。好吧,谢谢你让我变得聪明了一点,也让我的旧思维得到了锻炼。我还认为值得花点时间,因为你很好地安排了所有的机制来支持答案中的所有陈述。谢谢,我