C++STL幾種常用容器簡要歸納
本文將簡要介紹STL中vector,queue,priority_queue,deque,set,multiset,map,bitset八種容器及其操作方法。
vector
使用此容器需在程式前加上標頭檔案#include< vector >。 vector可理解為變長陣列,基於倍增思想。當以已申請vector長度為m時,若實際長度n=m,則申請長度為2m的陣列,將內容轉移至新地址上,並釋放舊空間;刪除元素時,若n<=m/4,則釋放一半空間。 vector容器能像陣列一樣隨機訪問第i個數a[i],但不支援隨機插入,其將元素插入尾部時的攤還代價為3。
#include<vector> //標頭檔案 vector<int> a; vector<int> b[100]; struct rec{···}; vector<rec> c; //各種宣告 vector<int>::iterator it; //vector的迭代器,與指標類似 a.size() //返回實際長度(元素個數),O(1)複雜度 a.empty() //容器為空返回1,否則返回0,O(1)複雜度 a.clear() //把vector清空 a.begin() //返回指向第一個元素的迭代器,*a.begin()與a[0]作用相同 a.end() //越界訪問,指向vector尾部,指向第n個元素再往後的邊界 a.front() //返回第一個元素的值,等價於*a.begin和a[0] a.back() //返回最後一個元素的值,等價於*--a.begin()和a[size()-1] a.push_back(x) //把元素x插入vector尾部 a.pop_back() //刪除vector中最後一個元素
迭代器使用與指標類似,可如下遍歷整個容器
for ( vector<int>::iterator it=a.begin() ; it!=a.end() ; it++ )
queue
迴圈佇列queue需使用標頭檔案< queue >
queue<int> q; struct rec{···};queue<rec> q; //宣告 q.push(x); //從隊尾使元素x入隊,O(1) q.pop(x); //使隊首元素出隊,O(1) int x=q.front(); //詢問隊首元素的值,O(1) int y=q.back(); //詢問隊尾元素的值,O(1)
priority_queue
優先佇列priority_queue可理解為一個大根二叉堆,必須定義“小於號”,而int,string本身就能比較。同樣需要標頭檔案< queue >。 其宣告與queue相似。
priority_queue<int> q;
priority_queue<pair<int,int>> q;
q.push(x); //插入 O(log n)
q.pop(); //刪除堆頂元素 O(log n)
q.top(); //查詢堆頂元素 O(1)
可通過插入元素的相反數取出時再取反,或過載“小於號”的方式實現小根堆,通過懶惰刪除法實現隨機刪除操作。
deque
雙端佇列,是一個支援在兩端高效插入或刪除元素的連續線性儲存空間,可像陣列一樣隨機訪問,使用前加標頭檔案< deque >。
q.begin()/q.end() //頭/尾迭代器,與vector類似
q.front()/q.back() //頭/尾元素,與queue類似
q.push_back(x)/q.push_front(x) //從隊尾/隊頭入隊
q.pop_back(x)/q.pop_front(x) //從隊尾/隊頭出隊
q.clear() //清空佇列
clear複雜度為O(n),其餘為O(1)。
set/multiset
兩容器相似,但set為有序集合,元素不能重複,multiset為有序多重集合,可包含若干相等的元素,內部通過紅黑樹實現,支援的函式基本相同,同樣必須定義“小於號”運算子,標頭檔案為< set >。 其迭代器不支援隨機訪問,支援星號(*)結束引用,僅支援 ++ 、-- 兩個與算術有關的操作。迭代器it++,則指向從小到大排序的結果中排在it下一名的元素,兩操作時間複雜度均為O(log n)。
q.size()
q.empty()
q.clear()
q.begin()/q.end() //作用與上文幾種容器類似
q.insert(x) //將元素x插入集合中,O(log n)
q.find(x) //查詢等於x的元素,返回其迭代器,無則返回q.end(),O(log n)
q.lower_bound(x) //查詢>=x的元素中最小的一個,返回指向該元素的迭代器
q.upper_bound(x) //查詢>x的元素中最小的一個,返回指向該元素的迭代器
q.erase(it) //刪除迭代器it指向的元素,O(log n)
q.erase(x) //刪除所有等於x的元素,複雜度為O(k+log n),k為被刪除的元素個數
q.count(x) //返回等於x的元素個數,O(k+log n),k為元素x的個數
若想從multiset中刪除之多一個等於x的元素,可執行
if((it=q.find(x))!=q.end())
q.erase(it);
map
map容器是一個鍵值對key-value的對映。內部為一棵以key為關鍵碼的紅黑樹,key和value可以是任意型別,其中key必須定義“小於號”運算子,宣告方法為
map<key_type,value_type> name;
例如
map<long long,bool> vis;
map<string,int> hash;
q.size()
q.empty()
q.clear()
q.begin()/q.end() //作用與上文幾種容器類似
q.insert(x) //插入,引數為pair<key_type,value_type>
q.erase(it) //刪除,引數可以是pair或迭代器
q.find(x) //查詢key為x的二元組,返回其迭代器,無則返回q.end(),O(log n)
q[key] //可得到key對應的value,也可對key進行賦值,改變對應的value
//若查詢的key不存在,則會新建一個二元組(key,zero)。
bitset
bitset可看作一個多位二進位制數,每8位佔用1個位元組,相當於採用了狀態壓縮的二進位制陣列,並支援基本的位運算。一般以32位整數的運算次數為基準估算執行時間,n位bitset執行一次的位運算複雜度可視為n/32,效率較高。標頭檔案。 同樣具有~,&,|,^,<<,>>操作符,==,!=可比較二進位制數是否相等
bitset<10000> q; //宣告一個10000位的二進位制數
q[k] //表示q的第k位,可取值,賦值,最低位為q[0]
q.count() //返回有多少位1
q.none() //所有位都為0則返回true,至少1位為1則返回false
q.any() //所有位都為0則返回false,至少1位為1則返回true,與函式none相反
q.set() //把所有位變為1
q.set(k,v) //把第k位變為v,即q[k]=v
q.reset() //把所有位變為0
q.reset(k) //把第k位變為0,即q[k]=0
q.flip() //把所有位取反,即s=~s
q.flip(k) //把第k位取反,即q[k]^=1
此上所有容器均可視作一個前閉後開的結構。