1. 程式人生 > >STL 容器

STL 容器

top 鏈表 imap 伸縮 關系 pri color multi 配接器

一、概述

STL 對定義的通用容器分三類:順序性容器、關聯式容器和容器適配器。

順序性容器是一種各元素之間有順序關系的線性表。元素在順序容器中保存元素置入容器時的邏輯順序,除非用刪除或插入的操作改變這個位置,否則元素的位置保持為原來的位置。

關聯式容器是非線性的結構,包含二叉樹結構和hash結構。元素在關聯容器中沒有保存元素置入容器時的邏輯順序。但是關聯式容器提供了另一種根據元素特點排序的功能,這樣叠代器就能根據元素的特點“順序地”獲取元素。關聯容器另一個顯著的特點是它是以鍵值的方式來保存數據,就是說它能把關鍵字和值關聯起來保存,而順序性容器只能保存一種。

容器適配器。適配器是使一事物的行為類似於另一事物的行為的一種機制。容器適配器以某種容器作為底部結構,將其接口改變,使得它滿足與另一種數據結構的接口,例如借助deque分別實現stack和queue接口,借助vector實現priority_queue接口。

二、順序容器

1 .vector動態數組<連續存儲、隨機訪問、檢索快、只能在後端添加刪除>

vector是一個線性順序結構。相當於動態數組,其大小可以預先指定也可以不指定,並且自動擴展,它可以像數組一樣被操作。在創建一個vector 後,它會自動在內存中分配一塊連續的內存空間進行數據存儲,初始的空間大小可以預先指定也可以由vector 默認指定,這個大小即capacity ()函數的返回值。當存儲的數據超過分配的空間時vector 會重新分配一塊內存塊,但這樣的分配是很耗時的,在重新分配空間時它會做重新分配空間、拷貝與釋放原有空間三個動作。如果vector 保存的數據量很大時,這樣的操作一定會導致糟糕的性能(這也是vector 被設計成比較容易拷貝的值類型的原因)。所以說vector 不是在什麽情況下性能都好,只有在預先知道它大小的情況下vector 的性能才是最優的。

2.雙向循環鏈表list<不連續存儲、不支持隨機訪問、支持任意位置插入刪除>

list是一個線性鏈表結構,它的數據由若幹個節點構成,每一個節點都包括一個實際存儲的數據、一個前驅指針和一個後驅指針。它無需分配指定的內存大小且可以任意伸縮,這是因為它存儲在非連續的內存空間中,並且由指針將有序的元素鏈接起來。由於其結構的原因,list 隨機檢索的性能非常的不好,因為它不像vector 那樣直接找到元素的地址,而是要從頭一個一個的順序查找,這樣目標元素越靠後,它的檢索時間就越長。檢索時間與目標元素的位置成正比。雖然隨機檢索的速度不夠快,但是它可以迅速地在任何節點進行插入和刪除操作。因為list 的每個節點保存著它在鏈表中的位置,插入或刪除一個元素僅對最多三個元素有所影響,不像vector 會對操作點之後的所有元素的存儲地址都有所影響,這一點是vector不可比擬的。

3.雙向隊列deque<vector和list特點結合,支持隨機訪問、支持內部插入刪除>

deque是一種優化的、對序列兩端元素進行添加和刪除操作的基本序列容器。它允許較為快速地隨機訪問,但它不像vector 把所有的對象保存在一塊連續的內存塊,而是采用多個連續的存儲塊,並且在一個映射結構中保存對這些塊及其順序的跟蹤。向deque 兩端添加或刪除元素的開銷很小。它不需要重新分配空間,所以向末端增加元素比vector 更有效。實際上,deque 是對vector 和list 優缺點的結合,它是處於兩者之間的一種容器。deque有如下幾個特點:

vector、list和deque 的比較:vector 是一段連續的內存塊,而deque 是多個連續的內存塊,list 是所有數據元素分開保存。vector 的查詢性能最好,並且在末端增加數據也很好,除非它重新申請內存段;適合高效地隨機存儲。list是一個鏈表,任何一個元素都可以是不連續的;deque是介於兩者之間,它兼顧了數組和鏈表的優點。

三、關聯容器

set, multiset, map, multimap 是一種非線性的樹結構,具體的說采用的是一種比較高效的特殊的平衡檢索二叉樹—— 紅黑樹結構。因為關聯容器的這四種容器類都使用同一原理,所以他們核心的算法是一致的,但是它們在應用上又有一些差別,先描述一下它們之間的差別。

1.set ,又稱集合,實際上就是一組元素的集合,但其中所包含的元素的值是唯一的,且是按一定順序排列的,集合中的每個元素被稱作集合中的實例。因為其內部是通過鏈表的方式來組織,所以在插入的時候比vector快,但在查找和末尾添加上被vector 慢。

2.multiset ,是多重集合,其實現方式和set 是相似的,只是它不要求集合中的元素是唯一的,也就是說集合中的同一個元素可以出現多次。

3.map ,提供一種“鍵- 值”關系的一對一的數據存儲能力。其“鍵”在容器中不可重復,且按一定順序排列(其實我們可以將set 也看成是一種鍵-值關系的存儲,只是它只有鍵沒有值。它是map 的一種特殊形式)。由於其是按鏈表的方式存儲,它也繼承了鏈表的優缺點。

4.multimap和map的原理基本相似,它允許“鍵”在容器中可以不唯一。

5.unordered_map和map類似,都是存儲的key-value的值,可以通過key快速索引到value。不同的是unordered_map不會根據key的大小進行排序,存儲時是根據key的hash值判斷元素是否相同,即unordered_map內部元素是無序的,而map中的元素是按照二叉搜索樹存儲,進行中序遍歷會得到有序遍歷。所以在使用map的key時,需要定義operator<,而在使用unordered_map需要定義哈希函數,並且重載operator==

6.unordered_set類似

四、容器適配器

STL 中包含三種適配器:棧stack 、隊列queue 和優先級priority_queue。

1.stack 是一種先進後出(First In Last Out , FILO)的數據結構。它只有一個出口,stack 允許新增元素,移除元素,取得最頂端元素。但除了最頂端外,沒有任何其它方法可以存取stack的其它元素,stack不允許遍歷行為。以某種容器作為底部結構,將其接口改變,使之符合“先進後出”的特性,形成一個stack,是很容易做到的。deque是雙向開口的數據結構,若以 deque為底部結構並封閉其頭端開口,便輕而易舉地形成了一個stack.因此,SGI STL 便以deque作為缺省情況下的stack底部結構,由於stack 系以底部容器完成其所有工作,而具有這種"修改某物接口,形成另一種風貌"之性質者,稱為adapter(配接器),

2.queue是一種先進先出(First In First Out,FIFO) 的數據結構。它有兩個出口,queue允許新增元素,移除元素,從最底端加入元素,取得最頂端元素。但除了最底端可以加入,最頂端可以取出外,沒有任何其它方法可以存取queue的其它元素。以某種容器作為底部結構,將其接口改變,使之符合“先進先出”的特性,形成一個queue,是很容易做到的。deque是雙向開口的數據結構,若以 deque為底部結構並封閉其底部的出口和前端的入口,便輕而易舉地形成了一個queue.

3.heap和priority:heap 並不歸屬於STL容器組件,是priority queue的助手。priority queue允許用戶以任何次序將任何元素推入容器中,但取出時一定按從優先權最高的元素開始取。按照元素的排列方式,heap可分為max-heap和 min-heap兩種,前者每個節點的鍵值(key)都大於或等於其子節點鍵值,後者的每個節點鍵值(key)都小於或等於其子節點鍵值。因此, max-heap的最大值在根節點,並總是位於底層array或vector的起頭處;min-heap的最小值在根節點,亦總是位於底層array或 vector起頭處。

STL 容器