9.1 順序容器
- 性質:容器中元素的順序與加入的位置相對應,爲使用者提供了控制元素存儲和訪問順序的能力。
六大順序容器
名稱 功能 特點> vector 可變大小數組 支持快速隨機訪問,除尾部外插入、刪除較慢 deque 雙端隊列 支持快速隨機訪問,頭尾外插入刪除較慢 list 雙向列表 支持雙向順序訪問,任何位置插入刪除很快 forward_list 單項列表 支持正向順序訪問,任何位置插入刪除很快 array 固定大小數組 支持快速隨機訪問,不能添加刪除 string 字符串 支持快速隨機訪問,除尾部外插入、刪除較慢
- list與forward_list相較有更大的額外內存消耗。
- array相比內置數組更爲安全。
- 標準庫運行效率較高,應當優先選擇標準庫而不是原式數據結構。
- 如果程序只要在讀取時纔會向容器中間插入數據,可以設定一個list緩衝。
9.2順序容器概覽(一般操作)
類型與函數 | 描述 |
---|---|
iterator | 迭代器 |
const_iterator | 只讀迭代器 |
size_type | 無符號整型,描述容器大小或迭代器位置差 |
difference_type | 帶符號整型 |
value_type | 元素類型 |
reference | 元素左值類型,與value_type&相似 |
const_reference | const左值 |
C c, C c(c2), C c(b,e) | 構造函數 |
C c{a,b,c,d…} | 構造函數 |
C c(n), C c(n,t) | 構造函數,n爲個數,t爲初始值 |
c1=c2, c1={a,b,c,d,…} | 賦值 |
a.swap(b), swap(a,b) | 交換 |
c.size() | 元素個數(不支持forward_list) |
c.max_size() | 容器可保存最多元素個數 |
c.empty() | 確認容器是否爲空 |
c.insert(args) | 插入元素 |
c.emplace(inits) | 構造一個元素 |
c.erase(args) | 刪除元素 |
c.clear() | 清空容器 |
reverse_iterator | 逆尋址迭代器 |
const_reverse_iterator | 只讀逆尋址迭代器 |
c.rbegin(), c.rend(), c.crbegin(), c.crend | 返回逆尋址迭代器 |
對於C c(b,e)的構造方法,C所聲明的容器元素類型,必須與b e的類型相容(不一定一樣,除array)。
比較運算符必須要求容器中的元素允許元素運算。
迭代器有公共的接口,forward_list不支持自減操作。
對反向迭代器使用自增,等價於正向迭代器遞減。
迭代器初始化與拷貝初始化區別
list<string> ls; vector<const char*> vcc; list<string> ls2(ls);//正確無疑 deque<string>ds(ls);//錯誤,容器種類不同 vector<string>vs(vcc)//錯誤,容器元素類型不同 forward_list<string>fs(vcc.begin(),vcc.end());//正確
- array
- 支持容器直接拷貝(內置數組當然不行),但是類型和長度必須都一致。
- 不支持assign與列表賦值。
9.3 順序容器操作
賦值與交換
交換兩個容器的元素通常比拷貝元素快,除array不涉及任何元素拷貝、刪除、插入,故在常數時間完成。
賦值會導致左值容器的迭代器、引用、指針失效,而交換會導致所有迭代器、引用、指針失效(array,string除外)。
assign
- assign(b,e):b和e不能是調用容器的迭代器。
- assign(n,t):全部替換,沒有部分替換的方法。
交換兩個array用線性時間,但是元素值改變的同時迭代器所表示的位置不變。
添加元素
push_back()
- 不支持forward_list。
- 本質是添加拷貝。
- 返回void。
push_front
- 支持list,forward_list,deque。
- 在最開頭插入元素,返回void。
insert
對push_front不支持不代表對insert插入開頭不支持。
在迭代器指向元素之前插入,且返回第一個插入元素的迭代器。
通過將返回值賦值給原迭代器,可實現在同一位置反覆插入元素。
也有返回void版本的insert方法。
- emplace :直接進行初始化
訪問元素
front:返回首元素的引用,通過*(c.begin())也可得到。
back:返回尾元素的引用,forward_list無,通過*(c.end()-1)也可得到。
- at(n):返回下標爲n的元素的引用。
刪除元素
pop_front, pop_back
pop_back不支持forward_list,pop_front不支持vector、string。
分別刪除首元素與尾元素,容器不可爲空,返回void。
erase:
刪除單個或範圍元素,返回被刪除的最後一個元素之後的迭代器。
刪除單個尾後迭代器是未定義的,範圍包含尾後迭代器是可以的。
forward_list
- 特殊原因:作爲單向鏈表,無法通過簡答方法獲得元素的前驅,故通過改變給定元素之後的元素來實現。
insert_after:返回指向最後一個插入元素的迭代器。
emplace_after(p,args):插入元素args,返回指向插入元素的迭代器。
- erase_after(p):刪除p指向位置之後的元素,返回指向被刪除元素之後的迭代器。
erase_after(b,e):刪除[b,e)之間的元素,且返回指向被刪除元素之後的迭代器。
在forward_list中,通常會有兩個變量,一個記錄當前迭代器,一個記錄前驅迭代器。
forward_list<int> fl = {0,1,2,3,4,5,6,7,8,9}; auto prev=fl.before_begin(); auto curr=fl.begin(); while(curr!=fl.end()){ if (*curr % 2) curr = fl.erase_after(prev); else prev = curr++; }
注意點:一旦涉及到容器的插入刪除,不要緩存迭代器(end()),應當每次使用都調用一次。
9.4 vector對象的增長方式
- capacity:當前容器上限元素個數
- reserve:給容器分配更大的空間(小於等於當前空間不會報錯,但是什麼也不做)
shrink_to_fit:將上限減少到與size()相匹配的大小。
vector重新分配內存時一般上限*2。
9.5 string的額外操作
構造方法
(cp,n)
cp指向的數組中的,前n個元素的拷貝。如果不傳遞n,指針所指向的數組必須以 ‘\n’ 結尾!(s2,pos2)
從string類對象s2的下標pos2開始的拷貝,pos2大於s2.size()爲未定義的行爲。(s2,pos2,len2)
從string類對象s2的下標pos2開始len2個字符的拷貝,pos2大於s2.size()爲未定義的行爲,len2過長不影響正常運行。s.substr(pos,n)
返回字符串s從pos到pos+n-1的子串的拷貝。
其他操作
存在基於下標運算的insert、erase、assign方法。
append(args):類似於”+”。
- replace(range,args):range爲pos開始len長個字符,或者是一對迭代器。
搜索操作
返回值:string::size_type或string::npos。
find(args)
返回調用對象中第一個匹配s的位置的下標,不存在則返回npos。- rfind(args)
返回調用對象中最後一個匹配s的位置的下標,不存在則返回npos。 - find_first_of(args)、find_last_of(args)
返回第一次/最後一次args中任一字符出現的位置。 - find_first_not_of(args)、find_last_not_of(args)
返回第一次/最後一次不在args中出現的字符位置。 - 樣例:查找數字字符
#include <iostream> #include <cstring> using namespace std; int main(){ string s="ab2c3d7R4E6"; string sn="0123456789"; string::size_type pos=0; while((pos=s.find_first_of(sn,pos))!=string::npos){ cout<<s[pos]<<endl; pos++; } pos=0; while((pos=s.find_first_not_of(sn,pos))!=string::npos){ cout<<s[pos]<<endl; pos++; } return 0; }
compare方法:類似於strcmp。
- 數值轉換:一般爲sto + 類型首字母 + (s,p,b),p爲第一個非數值字符的下標,b爲基數默認10。
string s="a=1"; int i=stoi(s.substr(s.find_first_of(0123456789)));
9.6 順序容器適配器
定義:接受一種已有容器,並使其有接收適配器的操作。
定義適配器
與容器定義類似。
默認下,stack 和 queue 是基於deque實現的,而priority_queue是基於vector實現的。
通過創建適配器時將命名的順序容器作爲第二個參數,可以重載默認容器類型。
stack<string, vector<string>>str_stk(svec);
限制
- 適配器不能構造於array、forward_list之上。
- queue不能構造於vector之上,priority_queue不能構造於list之上。
- 適配器不可以調用底層容器專有的方法。
特徵
- queue:先進先出,即進入隊列的對象被放置到對尾。
- priority_queue:新加入的元素排在優先級比其低的元素之前。