STL各容器的底層實現及其優缺點


STL各容器的底層實現及其優缺點

序列式容器

​ 序列式容器,即以線性排列(類似普通數組的存儲方式)來存儲某一指定類型(例如 int、double 等)的數據,需要特殊說明的是,該類容器並不會自動對存儲的元素按照值的大小進行排序。C++本身提供了array序列式容器,也就是普通的數組。

1.vector

​ vector和array很相似,唯一的區別是,array是靜態空間,大小一旦配置就無法更改。而vector是動態空間,更加靈活,隨着元素的增加,其內部機制會自動擴容。vector所采用的數據結構為線性連續空間,為了防止頻繁的擴容,vector在配置時一般會配置比用戶需求更大的空間,這就是容量的概率。容量始終是大於等於vector實際大小的。當滿載時,會以原大小的兩倍配置一塊新空間,將原空間的內容拷貝過來,釋放原空間。這時要注意原有的迭代器都會失效。

​ 由於vector底層線性連續空間的特點,其在尾部插入、刪除元素的效率最高,為O(1)。但其它位置的插入刪除效率為O(n)。vector是隨機存取的,所以訪問任意的效率較高。

2.list

​ 相較於vector的連續線性空間,list每次插入或刪除一個元素,就是配置獲釋放一個元素空間。list是一個雙向列表,其底層數據結構為一個雙向環狀列表,通過在環狀列表尾部添加一個空節點,使其滿足STL前閉后開的要求。

​ 因為雙向鏈表的特點,list插入刪除元素的效率為O(1);但訪問任意元素的速度較慢,因為其不支持隨機訪問,只能從頭尾開始遍歷。

3.deque

​ deque表現為一個雙向列表。其底層實現是,動態的分段連續空間,不同於vector的一整塊連續空間,deque是通過中控器將分散的內存塊連成一塊,並動態的增加減少,可以說是邏輯上的連續空間。也因為其底層實現的復雜,除非必要,應盡量使用vector。對於deque的排序,為了提高效率,可以先復制到vector中排序,然后再復制回deque。

​ 得益於deque的底層實現,其在頭尾插入刪除元素為O(1),但在任意位置插入刪除元素的時間復雜度為O(n)。

4. Stack,queue

​ stack,queue都是容器配接器,其底層是基於其它容器實現。stack的特點是元素先進后出,queue的特點是先進后出。

5. priority_queue

​ 優先隊列,是一個帶有價值觀念的queue,其內的元素並非按照被推入的順序排列,而是自動按照元素的權值排列。權值最高者,排在最前面。缺省情況下,STL中的priority_queue基於一個max_heap(大根堆),而后者是一個vector變現的完全二叉樹(complete binary tree)。

關聯式容器

​ 關聯式容器不同於序列式容器,在存儲元素值的同時,還會為各元素額外再配備一個值(稱為“鍵”),它的功能是在使用關聯式容器的過程中,如果已知目標元素的鍵的值,則直接通過該鍵就可以找到目標元素,而無需再通過遍歷整個容器的方式。棄用序列式容器,轉而選用關聯式容器存儲元素,往往就是看中了關聯式容器可以快速查找、讀取或者刪除所存儲的元素,同時該類型容器插入元素的效率也比序列式容器高。

面對關聯式容器,應該使用容器所提供的find函數來搜尋元素,會比STL算法find()更有效率。因為STL算法find()只是循環搜尋。

關聯式容器沒有所謂頭尾,只有最大、最小元素,所以沒有,push_back(),pus_front()這類的操作。

1. map, set , multimap, multiset

​ 之所以把這四種容器放在一起,是因為它們的底層實現都是基於紅黑樹。

​ map的特性是,所有元素會依據元素的鍵值自動被排序。map的所有元素都是pair,即鍵值對(value和key),map不允許擁有相同的鍵值。map不允許修改鍵值,允許修改實值。

​ set的特性是,所有元素會依據元素的鍵值自動被排序。set的元素,鍵值就是實值,實值就是鍵值,set不允許兩個元素有相同的元素。同時,由於set元素的特點,set的元素值是只讀的,因為set的值是其排列規則的依據,如果隨意修改,會破壞set 的組織。

​ multimap,multiset和map,set的唯一區別就是前者允許鍵值重復。

2. unordered_map,unordered_set, unordered_multimap, unordered_multiset

​ 這四種容器和非unordered版本的區別在於其底層實現,這四種均是基於hash表實現,所以默認是沒有順序的。

​ 選擇依據:

  • 基於RB-tree的關聯式容器,空間占用率高,因為map內部實現了紅黑樹,雖然提高了運行效率,但是因為每一個節點都需要額外保存父節點、孩子節點和紅/黑性質,使得每一個節點都占用大量的空間。其查找時間復雜度為O(logn)。此外,容器內的元素是有序的。
  • 基於hash表的關聯式容器,建表的過程時間消耗大,查找效率高,為O(1),適用於有頻繁的查找的情況。元素內的元素是無序的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM