在實際的開發過程中,數據結構本身的重要性不會遜於操作於數據結構的算法的重要性,當程序中存在着對時間要求很高的部分時,數據結構的選擇就顯得更加重要。經典的數據結構數量有限,但是我們常常重複着一些爲了實現向量、鏈表等結構而編寫的代碼,這些代碼都十分相似,只是爲了適應不同數據的變化而在細節上有所出入。STL容器就爲我們提供了這樣的方便,它允許我們重複利用已有的實現構造自己的特定類型下的數據結構,通過設置一些模版類,STL容器對最常用的數據結構提供了支持,這些模板的參數允許我們指定容器中元素的數據類型,可以將我們許多重複而乏味的工作簡化。
容器部分主要由頭文件<vector>,<list>,<deque>,<set>,<map>,<stack>和<queue>組成。對於常用的一些容器和容器適配器(可以看作由其它容器實現的容器),可以通過下表總結一下它們和相應頭文件的對應關係。
數據結構 描述 實現頭文件
向量(vector) 連續存儲的元素 <vector>
列表(list) 由節點組成的雙向鏈表,每個結點包含着一個元素 <list>
雙隊列(deque) 連續存儲的指向不同元素的指針所組成的數組 <deque>
集合(set) 由節點組成的紅黑樹,每個節點都包含着一個元素,節點之間以某種作用於元素對的謂詞排列,沒有兩個不同的元素能夠擁有相同的次序 <set>
多重集合(multiset) 允許存在兩個次序相等的元素的集合 <set>
棧(stack) 後進先出的值的排列 <stack>
隊列(queue) 先進先出的執的排列 <queue>
優先隊列(priority_queue) 元素的次序是由作用於所存儲的值對上的某種謂詞決定的一種隊列 <queue>
映射(map) 由{鍵,值}對組成的集合,以某種作用於鍵對上的謂詞排列 <map>
多重映射(multimap) 允許鍵對有相等的次序的映射 <map>
順序容器類型
順序容器
vector 支持快速隨機訪問
list 支持快速插入/刪除
deque 雙端隊列
順序容器適配器
stack 後進先出 (LIFO) 棧
queue 先進先出 (FIFO) 隊列
priority_queue 有優先級管理的隊列
容器構造函數
C<T> c; 創建一個名爲c的空容器.C是容器類型名,如vector,T是元素類型,如int或string.適用於所有容器.
C c(c2); 創建容器c2的副本c;c和c2必須具有相同的容器類型,並存放相同類型的元素.適用於所有容器
C c(b,e); 創建c,其元素是迭代器b和e標示的範圍內元素的副本.適用於所有容器
C c(n,t); 用n個值爲t的元素創建容器c,其中值t必須是容器類型C的元素類型的值,或者是可轉換爲該類型的值
只適用於順序容器
C c(n); 創建有n個值初始化元素的容器c
只適用於順序容器
容器元素類型必須滿足以下兩個約束:
元素類型必須支持賦值運算
元素類型的對象必須可以複製
常用迭代器運算
*iter 返回迭代器iter所指向的元素的引用
iter->mem 對iter進行解引用,獲取指定元素中名爲mem的成員.等效於(*iter).mem
++iter 給iter加1,使其指向容器裏的下一個元素
iter++
--iter 給iter減1,使其指向容器裏的前一個元素
iter--
iter1 == iter2 比較兩個迭代器是否相等.當兩個迭代器指向同一個容器中的同一
iter1 != iter2 個元素,或者當它們都指向同一個容器的超出末端的下一位置時,兩個迭代器相等
vector和deque容器的迭代器提供額外的運算
iter + n 在迭代器上加整數值n,將產生指向容器中前面第n個元素的迭代器.
iter - n 新計算出來的迭代器必須指向容器中的元素或超出容器末端的下一位置
iter1 += iter2 這是迭代器加減法的複合賦值運算:將iter1加上iter2的運算結果
iter1 -= iter2 賦給iter1
iter1 - iter2 兩個迭代器的減法,其運算結果加上右邊的迭代器即得左邊的迭代 器.這兩個迭代器必須指向一個容器中的元素或超出容器末端的下一位置
>, >=, <, <=
容器定義的類型別名
size_type 無符號整型,足以存儲此榮天氣類型的最大可能容器長度
iterator 此容器類型的迭代器類型
const_iterator 元素的只讀迭代器類型
reverse_iterator 按逆序尋址元素的迭代器
const_reverse_iterator 元素的只讀逆序迭代器
difference_type 足夠存儲兩個迭代器差值的有符號整型,可爲負數
value_type 元素類型
reference 元素的左值類型,是value_type&的同義詞
const_reference 元素的常量左值類型,等效於const value_type&
例:
list<string>::iterator iter;
vector<int>::difference_type cnt;
容器的begin和end操作
c.begin() 返回一個迭代器,它指向容器c的第一個元素
c.end() 返回一個迭代器,它指向容器c的最後一個元素的下一位置
c.rbegin() 返回一個逆序迭代器,它指向容器c的最後一個元素
c.rend() 返回一個逆序迭代器,它指向容器c的第一個元素前面的位置
在順序容器中添加元素的操作
c.push_back(t) 在容器c的尾部添加值爲t的元素.返回void類型
c.push_front(t) 在容器c的前端添加值爲t的元素.返回void類型
只適用於list和deque容器類型
c.insert(p,t) 在迭代器p所指向的元素前面插入值爲t的新元素.返回指向新元素的迭代器
c.insert(p,n,t) 在迭代器p所指向的元素前面插入n個值爲t的新元素.返回void類型
c.insert(p,b,e) 在迭代器p所指向的元素前面插入由迭代器b和e標記的範圍內的元素.返回void類型
例:
1.在容器中的指定位置添加元素
2.插入一段元素
3.避免存儲end操作返回的迭代器
順序容器的大小操作
c.size() 返回容器c中的元素個數.返回類型爲c::size_type
c.max_size() 返回容器c可容納的最多元素個數返回類型爲c::size_type
c.empty() 返回標記容器大小是否爲0的布爾值
c.resize(n) 調整容器c的長度大小,使其能容納n個元素如果n<c.size(),則刪除多出來的元素;否則,添加採用值初始化的新元素
c.resize(n,t) 調整容器c的長度大小,使其能容納n個元素.所有新添加的元素值都爲t
訪問順序容器內元素的操作
c.back() 返回容器c的最後一個元素的引用.如果c爲空,則該操作未定義
c.front() 返回容器c的第一個元素的引用.如果c爲空,則該操作未定義
c[n] 返回下標爲n的元素的引用
如果n<0或n>=c.size(),則該操作未定義
只適用於vector和deque容器
c.at(n) 返回下標爲n的元素的引用.如果下標越界,則該操作未定義
只適用於vector和deque容器
例:
刪除順序容器內元素的操作
c.erase(p) 刪除迭代器p所指向的元素
返回一個迭代器,它指向被刪除元素後面的元素.如果p指向容器內的最後一個元素,則返回的迭代器指向容器的超出末端的下一位置.如果p本身就是指向超出末端的下一位置的迭代器,則該函數爲定義
c.erase(b,e) 刪除迭代器b和e所標記的範圍內所有的元素
返回一個迭代器,它指向被刪除元素段後面的元素.如果e本身就是指向超出末端的下一位置的迭代器,則返回的迭代器也指向容器的超出末端的下一位置
c.clear() 刪除容器c內的所有元素.返回void
c.pop_back() 刪除容器c的最後一個元素.返回void.如果c爲空容器,則該函數未定義
c.pop_front() 刪除容器c的第一個元素.返回void.如果c爲空容器,則該函數未定義
只適用於list或deque容器
注:erase,pop_front和pop_back函數使指向被刪除的所有迭代器失效.
例:
順序容器的賦值操作
c1 = c2 刪除容器c1的所有元素,然後將c2的元素複製給c1.c1和c2的類型(包括容器類型和元素類型)必須相同
c1.swap(c2) 交換內容:調用完該函數後,c1中存放的是c2原來的元素,c2中存放的則是c1原來的元素.c1和c2的類型必須相同.該函數的執行速度通常要比將c2的元素複製到c1的操作快
c.assign(b,e) 重新設置c的元素:將迭代器b和e標記的範圍內所有的元素複製到c中b和e必須不是指向c中元素的迭代器
c.assign(n,t) 將容器c重新設置爲存儲n個值爲t的元素
例:
// equivalent to slist1 = slist2
slist1.assign(slist2.begin(), slist2.end());
使用swap不會使迭代器失效:
一個迭代器iter指向svec1[3]字符串;實現swap運算後,該迭代器則指向svec2[3]
關聯容器
關聯容器和順序容器的本質差別在於:關聯容器通過鍵(key)存儲和讀取元素,而順序容器則通過元素在容器中的位置順序存儲和訪問元素。
關聯容器(associative container)支持通過鍵來高效地查找和讀取元素。兩個基本的關聯容器類型是map和set。map的元素以鍵-值(key-value)對的形式組織:鍵用作元素在map中的索引,而值則表示所存儲和讀取的數據。set僅包含一個鍵,並有效地支持關於某個鍵是否存在的查詢
表10-1 關聯容器類型
map 關聯數組:元素通過鍵來存儲和讀取
set 大小可變的集合,支持通過鍵實現的快速讀取
multimap 支持同一個鍵多次出現的map類型
multiset 支持同一個鍵多次出現的set類型
與之相關的簡單的標準庫類型----pair類型
#include <utility>
表10-2 pair類型提供的操作
pair<T1, T2> p1; 創建一個空的pair對象,它的兩個元素分別是T1和T2類型,採用值初始化(3.3.1節)
pair<T1, T2> p1(v1, v2); 創建一個pair對象,它的兩個元素分別是T1和T2類型,其中first成員初始化爲v1,而second成員初始化爲v2
make_pair(v1, v2) 以v1和v2值創建一個新的pair對象,其元素類型分別是v1和v2的類型
p.first 返回p中名爲first的(共有)數據成員
p.second 返回p中名爲second的(共有)數據成員
例:pair的創建和初始化
pair<string, string> anon;
pair<string, int> word_count;
pair<string, vector<int> > line;