1. 程式人生 > >C++ STL 幾個容器的底層實現 收藏一下

C++ STL 幾個容器的底層實現 收藏一下

stl容器區別: vector list deque set map (轉)

在STL中基本容器有: vector、list、deque、set、map

set 和map都是無序的儲存元素,只能通過它提供的介面對裡面的元素進行訪問

set:集合, 用來判斷某一個元素是不是在一個組裡面,使用的比較少
map:對映,相當於字典,把一個值對映成另一個值,如果想建立字典的話使用它好了
底層採用的是樹型結構,多數使用平衡二叉樹實現,查詢某一值是常數時間,遍歷起來效果也不錯, 只是每次插入值的時候,會重新構成底層的平衡二叉樹,效率有一定影響.

vector、list、deque是有序容器
1.vector


vector就是動態陣列.它也是在堆中分配記憶體,元素連續存放,有保留記憶體,如果減少大小後,記憶體也不會釋放.如果新值>當前大小時才會再分配記憶體.

它擁有一段連續的記憶體空間,並且起始地址不變,因此它能非常好的支援隨即存取,即[]操作符,但由於它的記憶體空間是連續的,所以在中間進行插入和刪除會造成記憶體塊的拷貝,另外,當該陣列後的記憶體空間不夠時,需要重新申請一塊足夠大的記憶體並進行記憶體的拷貝。這些都大大影響了vector的效率。

對最後元素操作最快(在後面新增刪除最快 ), 此時一般不需要移動記憶體,只有保留記憶體不夠時才需要

對中間和開始處進行新增刪除元素操作需要移動記憶體,如果你的元素是結構或是類,那麼移動的同時還會進行構造和析構操作,所以效能不高 (最好將結構或類的指標放入vector中,而不是結構或類本身,這樣可以避免移動時的構造與析構)。


訪問方面,對任何元素的訪問都是O(1),也就是是常數的,所以vector常用來儲存需要經常進行隨機訪問的內容,並且不需要經常對中間元素進行新增刪除操作.

相比較可以看到vector的屬性與string差不多,同樣可以使用capacity看當前保留的記憶體,使用swap來減少它使用的記憶體.

capacity()返回vector所能容納的元素數量(在不重新分配記憶體的情況下)      測試push_back  1000個數據  capacity返回16384

總結
需要經常隨機訪問請用vector

2.list
list就是雙向連結串列,元素也是在堆中存放,每個元素都是放在一塊記憶體中,它的記憶體空間可以是不連續的,通過指標來進行資料的訪問,這個特點使得它的隨機存取變的非常沒有效率

,因此它沒有提供[]操作符的過載。但由於連結串列的特點,它可以以很好的效率支援任意地方的刪除和插入。

list沒有空間預留習慣,所以每分配一個元素都會從記憶體中分配,每刪除一個元素都會釋放它佔用的記憶體.

list在哪裡新增刪除元素效能都很高,不需要移動記憶體,當然也不需要對每個元素都進行構造與析構了,所以常用來做隨機操作容器.
但是訪問list裡面的元素時就開始和最後訪問最快
訪問其它元素都是O(n) ,所以如果需要經常隨機訪問的話,還是使用其它的好

總結
如果你喜歡經常新增刪除大物件的話,那麼請使用list
要儲存的物件不大,構造與析構操作不復雜,那麼可以使用vector代替
list<指標>完全是效能最低的做法,這種情況下還是使用vector<指標>好,因為指標沒有構造與析構,也不佔用很大記憶體

3.deque
deque是一個雙端佇列(double-ended queue),也是在堆中儲存內容的.它的儲存形式如下:
[堆1]
...
[堆2]
...
[堆3]
每個堆儲存好幾個元素,然後堆和堆之間有指標指向,看起來像是list和vector的結合品.

它支援[]操作符,也就是支援隨即存取,可以讓你在前面快速地新增刪除元素,或是在後面快速地新增刪除元素,然後還可以有比較高的隨機訪問速度,和vector的效率相差無幾,它支援在兩端的操作:push_back,push_front,pop_back,pop_front等,並且在兩端操作上與list的效率也差不多。
在標準庫中vector和deque提供幾乎相同的介面,在結構上它們的區別主要在於這兩種容器在組織記憶體上不一樣,deque是按頁或塊來分配儲存器的,每頁包含固定數目的元素.相反vector分配一段連續的記憶體,vector只是在序列的尾段插入元素時才有效率,而deque的分頁組織方式即使在容器的前端也可以提供常數時間的insert和erase操作,而且在體積增長方面也比vector更具有效率

總結:
vector是可以快速地在最後新增刪除元素,並可以快速地訪問任意元素
list是可以快速地在所有地方新增刪除元素,但是隻能快速地訪問最開始與最後的元素
deque在開始和最後新增元素都一樣快,並提供了隨機訪問方法,像vector一樣使用[]訪問任意元素,但是隨機訪問速度比不上vector快,因為它要內部處理堆跳轉
deque也有保留空間.另外,由於deque不要求連續空間,所以可以儲存的元素比vector更大,這點也要注意一下.還有就是在前面和後面新增元素時都不需要移動其它塊的元素,所以效能也很高。

因此在實際使用時,如何選擇這三個容器中哪一個,應根據你的需要而定,一般應遵循下面
的原則:
1、如果你需要高效的隨即存取,而不在乎插入和刪除的效率,使用vector
2、如果你需要大量的插入和刪除,而不關心隨即存取,則應使用list
3、如果你需要隨即存取,而且關心兩端資料的插入和刪除,則應使用deque。