为啥我们需要一个“循环链表”(单或双)数据结构?
Posted
技术标签:
【中文标题】为啥我们需要一个“循环链表”(单或双)数据结构?【英文标题】:Why exactly do we need a "Circular Linked List" (singly or doubly) data structure?为什么我们需要一个“循环链表”(单或双)数据结构? 【发布时间】:2011-04-05 02:57:25 【问题描述】:为什么我们需要一个“循环链表”(单或双)数据结构?
简单的链表(单链表或双链表)明显解决了哪些问题?
【问题讨论】:
我把上面的评论读成“为什么我们需要一个循环链表?因为 SO 的目标是成为正确的第一位......”然后我读了前面的“-1 " 评论:D 【参考方案1】:循环链表可以有效地用于创建队列(FIFO)或双端队列(高效的前后插入和删除)。见http://en.wikipedia.org/wiki/Linked_list#Circularly-linked_vs._linearly-linked
【讨论】:
【参考方案2】:使用它们的两个原因:
1) 一些问题域本质上是循环的。
例如,大富翁棋盘上的方块可以用循环链表表示,以映射到它们的固有结构。
2) 一些解决方案可以映射到循环链表以提高效率。
例如,抖动缓冲区是一种缓冲区,它从网络获取编号的数据包并将它们按顺序放置,以便(例如)视频或音频播放器可以按顺序播放它们。太慢(滞后)的数据包将被丢弃。
这可以在一个循环缓冲区中表示,而无需不断分配和释放内存,因为插槽可以在播放后重复使用。
它可以用链表来实现,但是会不断地对链表进行添加和删除,而不是替换为常数(更便宜)。
【讨论】:
我为游戏编写的粒子系统使用粒子的循环列表。如果我们用完了未使用的粒子(由于性能和内存原因而受到限制),那么我们只需覆盖最旧的粒子(这将只是在循环的“开始”,因为我们写到后面)。 抱歉,我无法为我的声明提供网络链接。称之为原创研究。 :-) 垄断板是一个发明的例子来说明这个想法。我从未见过 Monopoly 实现的代码。抖动缓冲区示例基于我开发和/或处理的一些代码示例。 普通的链表加上循环就不能解决这些问题吗? @day 当然。但是,使用循环列表,您可以用算法复杂性来换取(相当小的)结构复杂性。有一个循环意味着至少有一个额外的检查,而使用循环列表,你的结构本质上就是为你解决这个问题。【参考方案3】:我从谷歌找到的东西。
单链循环链表是链表中最后一个节点指向链表第一个节点的链表。循环列表不包含 NULL 指针。
应该使用循环链表的应用程序的一个很好的例子是操作系统解决的分时问题。
在分时环境中,操作系统必须维护一个当前用户列表,并且必须交替允许每个用户使用一小部分 CPU 时间,一次一个用户。操作系统会选择一个用户,让他/她使用少量的 CPU 时间,然后转移到下一个用户,等等。
对于这个应用程序,除非绝对没有人请求 CPU 时间,否则不应有 NULL 指针。
【讨论】:
【参考方案4】:一个简单的例子是在多人棋盘游戏中跟踪轮到谁。将所有玩家放在一个循环链表中。轮到一名玩家后,前进到列表中的下一位玩家。这将导致程序在玩家之间无限循环。
要遍历循环链表,请存储指向您看到的第一个元素的指针。当您再次看到该元素时,您已经遍历了整个列表。
void traverse(CircularList *c)
if (is_empty(c))
return;
CircularList start = c;
do
operateOnNode(c);
c = c->next;
while(c != start);
【讨论】:
一般遍历还需要if (!is_empty(c))
...
围绕整个do .. while
循环。
在单个链表中使用if(!c) c=head;
而不是实现这个是不是太难了?
@omerfarukdogan(延迟响应!)这是需要在每个节点上应用的额外检查。 (记住开始可能是链表的一半。)通过使链表循环来摆脱检查更有效,并且无需在每次导航之前进行测试。【参考方案5】:
循环列表比普通的双向链表更简单。 Append 只是 prepend 并向前移动一次,Pop back 只是向后移动一次并 pop front。通过将两端捆绑在一起,您将获得一个双端列表,而成本仅为实现单端列表的操作。
【讨论】:
用你的话来说,循环列表是一个两端连接的单个列表。好的,但这有什么好处?【参考方案6】:应用程序
1) 我们可以使用循环链表任何条目以旋转方式出现的应用程序。 2)循环链表是循环调度算法的基本思想。
【讨论】:
【参考方案7】:我们可以在资源池中使用循环链表。如果很多用户想使用一个共享资源,我们可以使用循环链表来分配该资源。
【讨论】:
【参考方案8】:应该使用循环链表的应用程序的一个很好的例子是操作系统解决的分时问题。
【讨论】:
【参考方案9】:循环链表广泛用于需要重复任务的应用程序或分时应用程序。循环队列可以跟踪已经执行和必须执行的任务,一旦特定任务完成就跳转到下一个任务,当整组任务完成后再次跳转到第一个任务完成剩余的工作。 实际使用中:当您在系统上打开多个应用程序时,这些应用程序的内存以循环方式保存,如果您连续按win+tab/alt+tab切换应用程序,您可以观察到这一点。 同样在多人棋盘游戏中,每个玩家都被分配到链表中的节点并执行轮换
【讨论】:
【参考方案10】:循环链表(单链表或双链表)对于需要平等访问每个节点的应用程序非常有用并且链表可能会增长。如果列表的大小是固定的,那么使用循环队列会更有效(速度和内存)。
【讨论】:
以上是关于为啥我们需要一个“循环链表”(单或双)数据结构?的主要内容,如果未能解决你的问题,请参考以下文章