繁体   English   中英

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

[英]C++ default implementation of stack and queue

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

我想知道为什么他们不使用list 堆栈和队列不支持随机访问,总是在两端操作,因此list应该是实现它们的最直观的方式,并且支持随机访问(具有恒定时间)的deque在某种程度上是不必要的。

有谁能解释这个实施背后的原因?

使用std::list作为底层容器,每个std::stack::push都进行内存分配。 std::deque以块的形式分配内存,并且可以重用其备用容量来避免内存分配。

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

主要原因是因为前后插入和删除的deque比平均列表更快

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

基准

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

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

让我们比较一下序列容器:

std::array是正确的,它不会改变大小。

std::list优化迭代器非失效,允许在已知位置插入,并且缺少随机访问。 它具有O(N)空间开销,具有大常量,并且具有错误的缓存局部性。

std::forward_list是一个更加残缺的list ,空间开销更小

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的原始访问速度中获益更多,保持堆不变。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM