阵列 – 基于阵列和基于列表的堆栈和队列

编辑:我很乐意被标记为非家庭作业,因为我不是学生,这不是任务。我从纯粹的好奇心中提出这个问题,因为我一直在为所有的列表使用Java ArrayList,最终发生在我身上,我应该知道所有这些结构和实现之间的区别。在花了一个周末阅读有关这些类型结构的所有相关(wikiepdia等)文章后,我仍然无法找到我在这篇文章中提出的问题。再次,不是功课

我试图比较堆栈和队列操作的增长率(运行时和空间),实现为数组和链表。到目前为止,我只能找到队列pop()的平均情况运行时间,但没有一个全面地探讨这两个数据结构并比较它们的运行时间/空间行为。

具体来说,我正在寻找将队列和堆栈的push()和pop()进行比较,实现为数组和链表(因此2个操作x 2个结构x 2个实现或8个值)。

此外,我会感谢这两个最佳的平均和最坏的情况值,以及与他们消耗的空间量有关的任何事情。

我最能找到的是这个“所有cs作弊书的母亲”pdf,这显然是高级算法和离散功能的硕士或博士级作文。

我只是在寻找一种方法来确定什么时候和在哪里我应该使用基于数组的实现与堆栈和队列的基于列表的实现。

有多种不同的方法来实现具有链接列表和数组的队列和堆栈,我不知道你要查找哪些。在分析任何这些结构之前,我们来回顾一下上述数据结构的一些重要运行时注意事项。

在一个只有一个头指针的单链表中,预先建立一个值的代价是O(1) – 我们只需创建一个新元素,将其指针连接到指向列表的旧头,然后更新头指针。删除第一个元素的成本也是O(1),这是通过更新头指针来指向当前头之后的元素来完成的,然后释放旧头的存储器(如果执行显式存储器管理)。然而,这些O(1)项中的常数因素可能由于动态分配的费用而高。由于在每个元素中存储额外的指针,链表的内存开销通常为O(n)个额外的内存。

在动态数组中,我们可以访问O(1)时间中的任何元素。我们还可以在amortized O(1)中附加一个元素,这意味着n个插入的总时间是O(n),尽管任何插入的实际时间范围可能会更差。通常,通过将大多数插入通过附加到预先分配的空间中,但是通过将阵列容量加倍并复制元素,少量插入在Θ(n)时间内运行,实现动态数组。有一些技术可以通过分配额外的空间和懒洋洋地复制元素来减少这种情况(例如参见this data structure)。通常,动态数组的内存使用情况非常好 – 当数组完全满时,例如,只有O(1)个额外的开销 – 尽管数组的大小已经翻倍了,可能有O(n)未使用在数组中分配的元素。由于分配不频繁,访问速度快,因此动态数组通常比链表快。

现在,我们来看一下如何使用链表或动态数组来实现堆栈和队列。有很多方法可以做到这一点,所以我会假设你正在使用以下的实现:

>堆栈:

>链接列表:作为singly-linked list带头指针。
> Array:作为dynamic array

>队列:

>链接列表:作为具有头和尾指针的单链表。
> Array:作为一个由数组支持的circular buffer

我们依次考虑一下。

堆叠由单链列表支持。因为单链表支持O(1)时间前置和删除优先,所以推送或弹出链接列表支持的堆栈的成本也是O(1)最坏的情况。然而,添加的每个新元素都需要新的分配,并且与其他操作相比,分配可能是昂贵的。

堆栈由动态数组支持。可以通过将一个新元素附加到动态数组来实现堆栈,这个元素需要分摊O(1)个时间和最坏情况的O(n)时间。从堆栈弹出可以通过删除最坏的情况下运行的最后一个元素(如果要尝试回收未使用的空间)(或摊销O(1)),则可以实现。换句话说,最常见的实现有最好的O(1)push和pop,最坏情况O(n)push和O(1)pop,以及摊销O(1)push和O(1)pop。

队列由单链列表支持。排入链表可以通过附加到单链表的背面来实现,这种情况在最坏的情况下是O(1)。可以通过删除第一个元素来实现出队,这也是最坏的时间O(1)。这也需要每个入队进行新的分配,这可能很慢。

队列由不断增长的循环缓冲区支持。通过在循环缓冲区中的下一个空闲位置插入某些东西,排入循环缓冲区。这可以通过增加数组,如果需要,然后插入新的元素。对动态数组使用类似的分析,这是最佳情况时间O(1),最坏情况时间O(n)和摊销时间O(1)。通过删除循环缓冲区的第一个元素,在最坏的情况下需要时间O(1),从缓冲区中排队。

总而言之,所有的结构都支持在O(n)时间内推动和弹出n个元素。链表版本具有更好的最坏情况行为,但是由于执行的分配数量,整个运行时间可能会更差。阵列版本在最坏情况下更慢,但是如果每个操作的时间不是太重要,则整体性能会更好。

VList是一个最新的数据结构,它是一个链表和动态数组的混合。它比链表更少的分配,并且在其中具有较少的指针,尽管在最坏的情况下空间使用率要高一些。您可能还需要查看可以用于堆栈和队列的chunklists,这些chunklists是数组和链表的另一个混合。

希望这可以帮助!

http://stackoverflow.com/questions/7477181/array-based-vs-list-based-stacks-and-queues

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:阵列 – 基于阵列和基于列表的堆栈和队列