堆栈和队列的C ++默认实现

时间:2018-07-10 13:06:36

标签: c++ c++11

C ++ Primer 5th 中,它表示stackqueue的默认实现是deque

我想知道为什么他们不使用list? Stack and Queue不支持随机访问,总是在两端都运行,因此list应该是实现它们的最直观的方式,而deque支持随机访问(具有固定时间)没必要。

任何人都可以解释这种实现背后的原因吗?

4 个答案:

答案 0 :(得分:10)

使用std::list作为基础容器,每个std::stack::push进行内存分配。 std::deque会按块分配内存,并且可以重用其备用容量以避免内存分配。

使用小元素,列表节点的存储开销也可能变得很大。例如。 std::list<int>节点大小为24个字节(在64位系统上),元素仅占用4个字节-至少有83%的存储开销。

答案 1 :(得分:4)

主要原因是因为前后插入和删除的双端队列平均速度高于列表

deque速度更快,因为内存是按块分配的,因为列表需要在每个元素上分配,而分配是昂贵的操作。

benchmark

答案 2 :(得分:4)

我认为应该反过来问:如果可以使用数组,为什么要使用列表?

该列表更加复杂:更多的分配,更多的资源(用于存储指针)和更多的工作(即使都是固定的时间)。另一方面,首选列表的主要属性也与堆栈和队列无关:恒定时间随机插入和删除。

答案 3 :(得分:0)

让我们比较序列容器:

std::array就可以了,它不会改变大小。

std::list优化了迭代器的无效性,允许在已知位置插入,并且缺乏随机访问权限。它具有O(N)个空间开销,且常数较大,并且缓存位置不正确。

std::forward_listlist残缺不全的文件,具有较小的空间开销

std::deque优化了追加或前置操作,但以不连续为代价。它具有O(N)个空间开销,且常数较小,并且缓存位置中等。

std::vector优化了访问速度,但要以插入/删除为代价,但要保留结尾处以外的位置。它具有O(1)的空间开销,并且具有很好的缓存局部性。

那么这对于堆栈和队列意味着什么?

std::stack只需要一端操作。 std::vectorstd::dequestd::list都提供了必要的操作

std::queue要求两端都进行操作。 std::dequestd::list是唯一的候选人。

选择std::deque作为默认设置是一种一致性,因为std::vector通常对std::stack更好,但不适用于std::queue

请注意,尽管std::priority_queue的名称类似于std::queue,但实际上它更类似于std::stack,只需要在一端进行修改。它还受益于std::vector的原始访问速度,从而使堆保持不变。