簡體   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