C++ ——常用STL容器
摘要
vector 變長陣列,倍增的思想
pair 儲存二元組
string 字串,substr(), c_str()
queue 佇列, push(),pop(),front()
priority_queue, 優先佇列,push(),pop(),top()
deque,雙端佇列
stack 棧, push(),pop(),top()
set,map,multiset,multimap, 基於平衡二叉樹(紅黑樹),動態維護有序序列
unordered_set, unordered_map, unordered_multiset,unordered_multimap,
bitset, 壓位
vector
基礎應用
#include <vector>
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; int main() { vector<int> a(n); //定義一個長度為n的int陣列 vector<int> a(10,1); //定義一個長度為10的int陣列,並把每個元素初始化為1 vecotor<int> a[10]; //定義一個vector陣列(10個vector) for(auto x : a) cout << x << endl; //遍歷陣列中的元素 a.size(); //返回vector中元素的個數 a.empty(); //a是否為空,若為空,返回true,否則,返回false a.clear(); //清空 return 0; }
size(); //返回vector中元素的個數
empty(); //a是否為空,若為空,返回true,否則,返回false
clear(); //清空
front(); //返回第一個元素
back(); //返回最後一個元素
push_back() / pop_back() //向vector末尾插入一個元素/把vecor最後一個元素刪除
迭代器 begin(); //vecor 的第0個元素 end(); //vecor的最後一個元素的後面一個元素
a.begin() = a[0]; a.end() = a[a.size()];
[] :vector支援隨機定址,和陣列一樣
黑科技
支援比較運算,按字典序來比較兩個vecor大小
int main()
{
vector<int> a(4,3),b(3,4);
if(a < b) puts("a < b");
return 0;
}
//輸出: a < b
注
size()和empty()所有容器都有,時間複雜度為O(1);
clear()函式並不是所有容器都有,queue 沒有;
auto可以遍歷所有容器。
倍增思想:自動變長,減少申請的次數。
系統為某一個程式分配空間時,所需時間基本上與空間大小無關,而只與申請次數有關
三種遍歷方法
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
int main()
{
vector<int> a;
for(int i = 0; i < 10; i ++ ) a.push_back(i);
//下標遍歷
for(int i = 0; i < a.size(); i++ ) cout << a[i] << ' ';
cout << endl;
//迭代器遍歷
for(vector<int> :: iterator i = a.begin(); i != a.end(); i ++ )
cout << *i << ' ';
cout << endl;
//範圍遍歷(程式碼短,效率高)
for(auto x : a) cout << x << ' ';
cout << endl;
return 0;
}
輸出樣例:
注:auto 用於總動推斷變數型別
例如上述程式碼,vector<int> :: iterator 也可以寫成 auto.
pair
用於儲存一個二元組
可以看做幫我們實現了一個結構體,而且自帶比較函式
定義方法:
pair< , >前後兩個變數型別可以任意
例如:pair<int,string> p;
構造pair(初始化):
p = make_pair(10,"abc");
或C ++ 11 中可以直接寫成 :p = {10,"abc"};
基礎應用:
p.first : 取pair的第一個元素;
p.second : 取pair的第二個元素
pair 支援比較運算,以first為第一關鍵字,以second為第二關鍵字(字典序)
常用情景:
某個東西有兩種不同的屬性,我們就可以用一個pair來存,可能用到某種屬性來排序,這時我們把要排序的關鍵字放到first裡,把不需要排序的關鍵字放到second裡,直接對pair排序就可以了。
假如某個東西有三種屬性,也可以用pair來存哦!這時我們可以用兩次pair,下面以int為例。
pair<int,pair<int,int>> p;
那麼可以通過巢狀的方式儲存任意多個。
string
C++把字串進行了封裝
基礎應用
支援size(),empty(),clear()
length()作用與size()相同,都是返回字串長度
可以在一個字串末尾加上字串或字元
int main()
{
string a = "abc";
a += "def";
a += "g";
cout << a << endl;
cout << a.substr(1,2) << endl;
printf("%s/n",a.c_str());
//用printf輸出一個string,要輸出字元陣列的起始地址
return 0;
}
//輸出:
// abcdefg
// bc
// abcdefg
substr(引數1,引數2); 返回某個子串
引數1:下標起始位置; 引數2:子串長度
當第二個引數很大,超出字串長度時,就會輸出到最後一個字串為止
也可以把第二個引數省略,就會直接返回從起始位置開始到末尾的整個子串。
c_str() 返回string儲存字串的起始地址
queue佇列
基礎應用
#include <queue>
支援size(),empty();
push() 向隊尾插入一個元素
pop()彈出隊頭元素
front()返回隊頭元素
back()返回隊尾元素
queue不支援clear()函式,若要清空,重新構造一個空的佇列就可以了
int main()
{
queue<int> q;
q = queue<int> ();
return 0;
}
priority_queue 優先佇列(堆)
基礎應用
支援size(),empty()
不支援cear()
push() 向堆中插入一個元素
top() 返回堆頂元素
pop()彈出堆頂元素
定義的堆預設為大根堆
那麼定義小根堆方法:
1.直接插入負數(-x從大到小,x就是從小到大的)
2.
int main() { //大根堆 priority_queue <int> heap; //小根堆 priority_queue <int,vector<int>,greater<int>> heap; return 0; }
stack 棧
基礎應用
支援size(),empty()
不支援clear()函式
push() 向棧頂插入一個元素
top()返回棧頂元素
pop()彈出棧頂元素
deque 雙端佇列
一個加強版的vector
很NB,但缺點是速度比較慢,效率低
支援size(),empty(),clear()
front(),back(),push_back(),pop_back()上面已經介紹過,這裡不再多說了。
push_front() 向隊首插入一個元素
pop_front() 從隊首彈出一個元素
[ ] : 支援隨機定址
begin() / end() 迭代器
set,map,multiset,multimap, 基於平衡二叉樹(紅黑樹),動態維護有序序列
支援size(),empty(),clear() 時間複雜度O(1)
增刪改查的操作 時間複雜度 為 O(logn)
begin(),end() 支援++ -- 返回前驅和後繼
set/multiset
#include <set>
定義:
set<int>S;
multiset<int>MS;
基礎應用
set 中不能有重複元素,如果我們插入了重複的元素,這個操作就會被忽略掉。
multiset中可以有重複元素。
下面所有操作的時間複雜度都是log(n)
二者均支援的操作:
insert() 插入一個元素
find() 查詢一個元素,若不存在,返回end()迭代器
count() 返回某個元素的個數 (當然,set中只有0和1兩種情況,multiset中有幾個就返回幾個)
erase():
1.輸入是一個數x,則刪除所有x;(mutiset中可能存在多個x) 時間複雜度O(k + log(n)) k是x的個數
2.輸入是一個迭代器,則刪除這個迭代器;
核心操作
lower_bound() / upper_bound()
lower_bound(x) 返回大於等於 x 的最小的數的迭代器
upper_bound(x) 返回大於x的最小的數的迭代器
若不存在返回 end()
map / multimap
#include<map>
map容器是一個鍵值對key-value的對映,其內部實現是一棵以key為關鍵碼的紅黑樹。Map的key和value可以是任意型別,其中key必須定義小於號運算子。
宣告
map<key_type, value_type> name;
例如:
map<long, long, bool> vis;
map<string, int> hash; //把string對映到int
map<pair<int, int>, vector<int>> test;
size/empty/clear/begin/end均與set類似。
Insert/erase
與set類似,但其引數均是pair<key_type, value_type>。
基礎應用
insert() 輸入的引數是一個pair
erase() 輸入的引數是pair 或 迭代器 都可以
支援find() ,lower_bound() / upper_bound()
核心操作
[ ] 可以像用陣列一樣用map
時間複雜度是O(logn)
int main()
{
map<string,int> a;
a["abc"] = 1;
cout << a["abc"] << endl;
return 0;
}
//輸出 1
unordered_set, unordered_map, unordered_multiset,unordered_multimap, 雜湊表
#include <unordered_xxx>
和上面類似,增刪改查的時間複雜度是O(1)
缺點:不支援lower_bound() / upper_bound()函式(內部是無序的), 迭代器的 ++ -- (凡是和排序有關的操作都是不支援的)
bitset, 壓位
例如:開一個長度為1024的bool陣列需要1024位元組=1kb(C ++ 中bool陣列是1位元組),如果我們把它壓到每一位中,沒一個位元組存八位,那麼就只需要開128個位元組,比正常的bool陣列省八倍記憶體,使用的空間是正常bool陣列的1/8。
再例如:如果我們想存一個10000*10000 的bool矩陣,需要個bool,大概是100MB的空間,而題目的空間限制是64MB,小於100MB,這個時候我們用bitset來存就只需要12MB就可以了。
定義:
bitset<10000> S; <>裡不是型別而是個數,這一點與前面的容器不同。
基礎應用
支援各種位運算操作 ~ , & , | , ^
移位操作 >> , <<
== , !=
[ ] 取出某一位是0還是1
count() 返回有多少個1
any() 判斷至少有一個1
none() 判斷是否全為0
set() 把所有位置1
set(k,v) 將第k為變成v
reset() 把所有位置0
flip() 等價於 ~(把所有位取反)
flip(k) 把第k位取反