实现队列的最佳数据结构是什么?

时间:2015-05-28 20:53:07

标签: data-structures queue

我只需要操作enque和dequeue。

3 个答案:

答案 0 :(得分:11)

从理论的角度来看,一个单独链接的列表,包括头部和尾部。从前面卸下,贴在尾巴上。在那里你有理论上的O(1)常数时间复杂度(即使对于最坏情况),存储量低于双向链表。

从实际角度来看,可扩展的基于阵列的连续结构可以使用循环索引更好地执行。由于空间局部性(例如,适合多个相邻元件的高速缓存行),硬件在处理连续存储器方面表现优异。那些算法复杂度更差,只有摊销的常数时间和最坏情况下的线性时间复杂度(尽管它很少见,通常无关紧要)。

同样从实际的角度来看,展开的列表可以很好地工作(基本上存储在链接在一起的节点中的多个元素的数组,为您提供引用的位置+保证的恒定时间队列和队列)。

“最好”在这里很难说,因为它取决于你的需求。

例如,具有尾部的单链接列表具有每个节点的分配/解除分配开销的弱点以及丢失的引用局部性,除非您使用有效的,连续的分配器来帮助缓解这些弱点。它还支付每个元素的列表指针/ ref的内存开销(由于每个节点的单独分配,可能还需要更多)。正如评论中所指出的那样,链接列表通常远不及它们听起来那么好,因为它们与硬件的实际性质不相符(至少没有来自分配器的大量帮助)。

圆形阵列有一个弱点,它需要多余的容量来减少重新分配的数量(或者更糟糕的线性时间复杂度将更频繁地开始)和副本(尽管在某些情况下它们可能很浅) 。此外,因为它只是一个大的连续内存块,如果你正在处理大量数据集,即使在具有虚拟寻址的机器上也可能会出现内存错误(内存不足并不意味着所有内存都已用完)在这种情况下,这意味着找不到与请求的大小匹配的连续的未使用页面集。)

展开的列表减轻了列表指针和节点分配开销,但是在节点中存储了一些过剩的容量,如果你使用一个展开的列表,每个节点可以存储64个元素,那么你可能会非常浪费只需在队列中存储3个元素。

答案 1 :(得分:4)

您可以使用数组(内存中的连续空格) 您还可以使用链接列表(不一定是连续的)

数组及其发烧友衍生物(ArrayList,vector等)可能更复杂。它们效率不高,因为如果开始添加太多元素,则可能会耗尽连续的内存空间,并且必须将队列中的所有内容复制到新的内存块中。

只要您跟踪正面和背面(头部和尾部,无论您想要什么称呼它),链接列表对我来说似乎非常有效。

这可能有所帮助:https://www.cs.bu.edu/teaching/c/queue/linked-list/types.html

答案 2 :(得分:2)

我不推荐array(或array之上实现的任何数据结构),因为dequeue操作将导致所有元素的移位。在这种情况下,我会转到最后插入的single ended linkedList并从开头删除但是如果要从最后删除则需要doubly linkedlist,因为你需要倒数第二个节点上的句柄来删除最后一个节点( dequeue}如果是单个指针linkedlist,则会导致扫描完整列表。