引述
C++ 的 STL 容器分為順序容器和關聯容器。
順序容器:vector、deque、list(forward_list)、array、string
關聯容器:map 和 set(及其 multi 和 無序版本)
容器適配器(不是容器):stack、queue、priority_queue
所謂的順序容器宏觀上理解就是小鬼們按一定的順序排排坐。關聯式包括類似于數據庫里面,有一個 key,有一個值這樣的。只有順序容器的構造函數才接受大小參數,關聯容器并不支持。
順序容器的 at 和下標操作值適用于 vector、string、deque、array。
容器那么多,操作那么雜,比如 array 不支持添加操作,forward_list 不支持 push_back,vector 和 string 不支持 push_front 等等,我也不住所有。既然如此,我們其實只要記一些關鍵容器的關鍵用法即可,其他等到需要的時候,百度查一查即可。下面,就是列出一些我們用得最多的容器的最最常用的一些操作和方法。
不考慮性能以及特殊數據結構專有特性,一般 vector+map+set+string 可以打天下了。記那么多干嘛,年紀大了,根本記不住。如果非要留一個,vector 其實也夠了。配上結構體,什么都能干,操作麻煩一點性能差一點而已了。
vector
用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
#include<iostream> #include<vector> #include <algorithm> using namespace std; int main() { vector< int > vec; vec.push_back(1); vector< int > vec1; vec1.resize(10); //10 個 0 vector< int > vec2(10); //10個元素,每個元素都是 0 vector< int > vec3(10, 1); //10 個 1 vec3.assign(10, 1); //分配 10 個 1 vector< int > vec4(vec3); vec.size(); vec.empty(); vec.front(); //返回一個元素,即迭代器start指向的元素 vec.back(); vector< int >::iterator it; it = vec1.begin() + 5; vec1.erase(it); //清除某個位置的元素 vec.clear(); //清除所有的元素 it = find(vec3.begin(), vec3.end(), 10); //查找 sort(vec3.begin(), vec3.end()); //vector沒有自帶排序方法,調用算法包,升序排序(默認) sort(vec3.begin(), vec3.end(), less< int >()); //升序排序 sort(vec3.begin(), vec3.end(), greater< int >()); //降序排序 for (auto& it : vec) it++; //C++11 方式引用變量 vec3.capacity();獲取包括備用空間在內的總容量大小 vec3.at(5);作用同上,增加異常處理,越界拋出out of range vec3.max_size(); //最大容量,即最多可以存儲多少個當前類型元素 vec3.pop_back(); //清除位于最后一個的元素 vec3.erase(vec3.begin(), vec3.end()); vec3.swap(vec2); reverse(vec.begin(), vec.end()); //元素翻轉 for ( int i = 0; i < vec.size(); i++) cout << vec[i] << endl; for (it = vec.begin(); it != vec.end(); it++) cout << *it << endl; for (auto it : vec) cout << it << endl; vector< int >::reverse_iterator rit; for (rit = vec.rbegin(); rit != vec.rend(); rit++) cout << *rit << endl; return 0; } |
其他說明
通常,使用 vecotr 是最好的選擇,除非你有很好的理由選擇其他容器。這也是我幾乎不介紹其他順序容器的原因。什么時候不用 vector 呢?比如說,當你基于性能的考慮,或者基于數據結構典型用法的考慮。這里說的數據結構典型性,指的是譬如你要寫的一個算法,用到了非常典型 “先進后出” 的特征,而且有高強度的彈出和推入的操作,這時候你不妨考慮用 stack,而不是 vector。
在 vector 中間插入是合法但是是耗時的。很多人寫算法,想到哪個就用哪個,這是很不對的,在選擇容器的時候,我們要考慮程序的性能。那么應該如何選擇合適的容器呢?如果你想表達的數據,stack 或者 queue 的特征已經非常明顯了,直接用他倆;如果對數據后續要有大量的查找,就用關聯式容器,其中又以無序的查找最快,但是它無序;如果有大量的添加和刪除操作(特別是在中間),選擇 list,而盡可能地避免 vector 和 array;如果對元素的次序要求比較高,且沒有元素在中間的插入或者刪除,且沒有極其大量的查找,可以選擇 vector 和 array…
vector 其實也支持 insert 操作,但是因為中間的插入對于 vector 來說是致命的耗時,所以我們一般不這么干,不這么干,那就沒寫這個了。
map
用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
#include<iostream> #include<map> using namespace std; int main() { map< int , string> st; st[0] = "str1" ; st[1] = "str3" ; st[2] = "str2" ; st.insert(make_pair(3, "str3" )); st.insert(pair< int ,string>(4, "str4" )); for (auto& it : st) cout << it.second << endl; for ( int i = 0; i < st.size(); i++) { //直接訪問 cout << st[i] << endl; } map< int , string>::iterator it = st.begin(); //通過迭代器訪問 for (it;it != st.end(); it++) { cout << it->first << " " << it->second << endl; } it = st.find(0); cout << it->first << " " << it->second << endl; st.erase(1); //通過鍵刪除 st.erase(st.find(0)); //通過迭代器(指針)刪除 st.erase(st.begin(), st.end()); //相當于st.clear() return 0; } |
其他說明
對一個 map 使用下標操作,其行為與數組或者 vector 上的下標操作很不相同:使用一個不在容器中的關鍵字作為下標,會添加一個具有此關鍵字的元素到 map 中。
map 是插入元素的時候就已經排好序了,當你需要排好序的數據結構的時候,可以考慮 map 和 set。
set
用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
#include<iostream> #include<set> using namespace std; int main() { set< int > s; s.insert(3); s.insert(5); s.insert(1); for (auto& it : s) cout << it << endl; set< int >::iterator it; for (it = s.begin();it != s.end(); it++) { cout << *it<< endl; } s.erase(s.find(1)); s.erase(3); s.erase(s.find(5), s.end()); //刪除了5,9 s.clear(); cout << s.size(); //輸出為 return 0; } |
其他說明
與 map 不同的地方,不能通過下標 key 來訪問了,只能直接 find。
string
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#include<cstdio> #include<string> using namespace std; int main() { //增 string str1 = "abc" ; string str2 = "def" ; string str = str1 + str2; str > str2; //字典序比較 str.insert(2, str1); //在下標為 2 的地方插入str1 str.insert(str.begin() + 1, str1.begin(), str1.end()); //刪 str.erase(str.begin() + 1); str.erase(str.begin() + 2, str.end()); str.erase(1, 2); //刪除從 1 開始的 2 個元素 //改 str.replace(0, 2, str1); //把起始位置為 0,長度為 2 的源子串替換為str1 str.replace(str.begin(), str.begin() + 2, str1); //查(包括訪問) int pos = str.find( "bc" ); //返回查找字符串第一次在源串中的位置 pos = str.find( "bc" , 2); //從源串的第 2 個位開始查找, 返回在 str 中的下標 for (auto& it : str) printf ( "%c\n" , it); // for (auto it = str.begin(); it < str.end(); it++) { printf ( "%c\n" , *it); } return 0; } |
用法
其他說明
string 和 vector 一樣,支持數字下標訪問。
直接讀入或者輸出一個 string 類型,用 cin 和 cout。str[i] 要用 printf 輸出的。
總結
到此這篇關于C++中最常用的容器用法與排序的文章就介紹到這了,更多相關C++容器用法與排序內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://blog.csdn.net/lusongno1/article/details/119988659