因網路上 STL 教程大多零散且缺乏嚴謹性,本文對演算法競賽所需 C++ Standard Library 做了一個較為全面的總結。
全文主要參考以下文件:
如有能力,閱讀原文可獲得更深入的瞭解。
1 STL 演算法
均在 #include<algorithm>
定義。
std::sort(first,last,cmp)
排序為不降序列。
接受隨機訪問迭代器。可自定義比較函式。
平均時間複雜度
,C++11 後嚴格 。std::stable_sort(first,last,cmp)
排序為不降序列,且保持相等元素的順序。
std::lower_bound(first,last,val,cmp)
返回指向首個不小於
val
的元素的迭代器,如無,返回last
。要求小於
val
的值和大於等於val
的值分居區間兩側。可自定義比較函式。若迭代器支援隨機訪問,對數時間複雜度,否則為線性。
std::upper_bound(first,last,val,cmp)
返回指向首個大於
val
的元素的迭代器,如無,返回last
。std::unique(first,last,cmp)
保留區間中所有連續等值區間的首個元素組成新序列,返回處理後序列的尾迭代器。
接受前向迭代器,可自定義判斷相等的函式。
線性時間複雜度。
2 基本或特殊容器
注:C++11 新引入的容器,大部分標頭檔案名與容器名一致。
pair
#include<utility>
:元素對。tuple
(C++11) :元組。bitset
#include<bitset>
:定長壓縮 01 串,可在 的時空複雜度內完成常見運算, 對應作業系統位數。string
#include<string>
:字串。
2.1 pair
operator=
:過載了賦值運算子用於複製。first
/second
:訪問第一項或第二項。std::make_pair(a,b)
:新建元素對,自動檢測型別。operator<=>
:過載了各種比較運算子,按第一關鍵字、第二關鍵字順序比較。
2.2 tuple
operator=
:過載了賦值運算子用於複製。std::get<i>(tp)
:獲取元組的第 i 項。std::get<T>(tp)
:獲取元組中型別為 T 的項。std::make_tuple(a,b,c,...)
:新建元組,自動檢測型別。operator<=>
:過載比較運算子,同樣是順序關鍵字比較。 …
2.3 string
與 vector
類似。其餘重要特性如下:
c_str()
:生成一個 C 風格字串(尾部置 0)並返回其頭部指標。length()
:size()
的同義函式。append(str)
:後方追加字串,返回*this
。append(first, last)
:區間插入版本。operator+
:連線兩個字串。compare(str)
:字典序比較。返回一個int
,用<0
/==0
/>0
判斷該字串小於 / 等於 / 大於引數字串。operator<=>
:字典序比較的運算子過載。substr(pos=0, count)
:返回[pos, min(pos+count, size()))
的子串。時間複雜度與count
成線性。pop_back()
(C++11)find(str)
/rfind(str)
/find_first_of(c)
/find_first_not_of(c)
/find_last_of(c)
/find_last_not_of(c)
:找字串或字元,返回位置。若無,返回npos=-1
。無時間複雜度保證,不建議使用。
2.4 bitset
bitset<N> bs(val / str)
:宣告一個長度為 N 的 bitset
並設定初值。
& / ! / ^ / ~ / >> / <<
:支援 AND / OR / XOR / NOT / 右移 / 左移等位運算系列。operator==
:判斷兩個bitset
是否相同。test(idx) / operator[idx]
:前者會做越界檢查,丟擲異常。size()
count()
:返回 1 的個數。all()
(C++11) :檢查是否全為 1。any() / none()
:檢查是否存在 1 / 沒有 1。set() / reset()
:所有位賦 1 / 0。flip()
:翻轉 0 / 1。
3 STL 容器概覽
以下部分均為 STL 容器相關內容。
3.1 迭代器
宣告:形如 vector<int>::iterator iter = xxx.begin()
。C++11 後可用 auto
代替型別宣告。
*iter
取值,iter++
後繼。
雙向迭代器可 iter--
,隨機訪問迭代器支援加減、比較運算。
begin()
,end()
:返回迭代器。end()
常作為 NULL 使用。cbegin()
,cend()
(C++11) :部分容器支援,返回只讀迭代器。rbegin()
,rend()
:部分容器支援,返回反向迭代器。crbegin()
,crend()
:部分容器支援,返回只讀反向迭代器。
3.2 公共性質
operator=
:過載了賦值運算子用於複製。empty()
:返回容器是否為空,即v.begin() == v.end()
。size()
:返回容器內元素個數。clear()
:清空容器。
4 序列式容器或容器介面卡
序列式容器:
array
(C++11) :定長順序表,常數隨機訪問。vector
#include<vector>
:順序表,常數後段插入,常數隨機訪問。deque
#include<deque>
:順序表,常數雙端插入,常數隨機訪問。list
#include<list>
:連結串列,常數插入刪除,雙向迭代器。forward_list
(C++11) :單向版本。
容器介面卡(均不支援迭代器):
queue
#include<queue>
:佇列(FIFO)。適配雙向變長序列式容器,即deque
(預設)或list
。stack
#include<stack>
:棧(LIFO)。適配變長序列式容器,即deque
(預設)、vector
或list
。priority_queue
#include<queue>
:大根堆。適配隨機訪問變長序列式容器,即vector
(預設)或deque
。
4.1 vector
Find:
crbegin()
at(idx)
/operator[idx]
:前者會做越界檢查,丟擲異常。front()
,back()
:返回首尾元素引用。
Modify:
push_back(x)
/pop_back()
:均攤常數複雜度。insert(iter, val)
:於迭代器iter
處插入,返回指向被插入元素的迭代器。insert(iter, first, last)
:左閉右開區間插入,返回指向首個被插入元素的迭代器。 注意,此操作非常數時間複雜度。erase(iter)
:於迭代器iter
處刪除,返回指向被刪除元素的後一個元素的迭代器。erase(first, last)
:左閉右開區間刪除,返回指向被刪除元素的後一個元素的迭代器。 注意,此操作非常數時間複雜度。
Size:
resize(n)
:改變長度,可指定補充元素預設值。shrink_to_fit()
:調整為恰好長度。
vector<bool>
被特殊定義,使用方式較為複雜,不建議使用。
4.2 deque
push_front(x)
,pop_front()
其餘與 vector
類似。
stack
top()
push(x)
pop()
queue
front()
push(x)
pop()
priority_queue
std::priority_queue<TypeName, Container, Compare>
:型別名,底層容器,比較型別。
大根堆,預設用 <
比較大小,即 Compare
傳入 std::less<T>
。亦可選擇傳入 std::greater<T>
使用 >
作為比較符號,進而構造出小根堆。
函式同 queue
,但 push() / pop()
為對數時間複雜度。
參照 std::less<T>
的實現,自定義比較方式,需傳入一個過載了 operator()
的結構體。
4.3 list
- 無隨機訪問介面。
insert(iter, val)
/erase(iter)
:插入與刪除變為常數時間複雜度,參見vector
。sort(cmp)
:為連結串列特殊設計的 穩定排序演算法。
其餘與 deque
類似。
5 關聯式容器
不支援隨機訪問,雙向迭代器,大部分操作為對數時間複雜度,紅黑樹實現。
set
/multiset
#include<set>
:元素有序。後者支援同值多元素。map
/multimap
#include<map>
:鍵有序。後者支援同鍵值多元素。
5.1 set / multiset
set<Key, Compare>
:類似 priority_queue
,可自定義比較方式。
Find:
crbegin()
count(x)
:返回值為x
的元素數量。lower_bound(x)
/upper_bound(x)
:為set
特殊定製的對數時間複雜度lower_bound
和upper_bound
。
沒有 nth_element()
,對數時間複雜度查詢第 k 大需手寫或使用 pbds 庫。
Modify:
insert(x)
:插入元素 x。返回pair<iterator, bool>
,表示插入元素的迭代器與插入是否成功。 對於multiset
,由於插入不會失敗,insert
只返回迭代器。erase(x)
:刪除所有值為 x 的元素,返回刪除元素的個數。erase(iter)
:刪除迭代器指向的元素,(C++11) 返回指向被刪除元素的後一個元素的迭代器。erase(first, last)
:左閉右開區間刪除,(C++11) 返回指向被刪除元素的後一個元素的迭代器。
刪除單個值為 x 的元素,可按如下方法進行:
auto it = s.find(x);
.erase(it); s
5.2 map / multimap
map<Key, T, Compare>
:可自定義比較方式。
- 對迭代器解引用得到
pair<Key, T>
。 insert(pair<Key, T>)
at[key]
/operator[key]
:前者會做越界檢查,丟擲異常。
其餘與 set
類似。
6 無序關聯式容器 (C++11)
單向迭代器,平均常數時間複雜度,Hash 實現。
若不支援 c++11,使用時需引入 TR1 擴充套件。例如,使用 unordered_map
需引入 #include<tr1/unordered_map>
標頭檔案,使用時需寫為 std::tr1::unordered_map
。
unordered_set
/unordered_multiset
#include<unordered_set>
:元素無序。unorderep_map
/unordered_multimap
#include<unordered_map>
:鍵無序。
只有單向迭代器,其餘特性與有序版本類似。
此外,可按如下方法自定義相等判定方式和 Hash 函式。
unordered_set<Key, Hash, KeyEqual>
unordered_map<Key, T, Hash, KeyEqual>
如上,可自定義 Hash 函式。