STL容器用法總結

vector 向量

可以說就是一個動態的數組,可以動態的增減容器中的元素數量。
需要頭文件#include <vector>

定義方式:vector<數據類型> 變量名稱;
size() //返回元素個數,時間複雜度O(1)
empty() //返回是否爲空,是則返回true,O(1)
clear() //清空該數組
front()/back() //返回首元素a[0]/尾元素a[n-1]
push_back() //在數組的最後面插入一個元素
pop_back() //刪除數組的最後一個元素
erase() //刪除迭代器指向的元素
begin() //返回一個迭代器,它指向容器vector的第一個元素(關於迭代器,最後會講到)
end() //返回一個迭代器,它指向容器vector的最後一個元素的下一個位置
[] //支持取下標,即a[0](注:大部分的stl容器其實都不支持這個操作)
注:支持比較運算,按字典序
舉例:

vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
cout<<a.size()<<endl;   //輸出3
cout<<a[0]<<' '<<a.front()<<endl;   //輸出都爲1
cout<<a[a.size()-1]<<' '<<a.back()<<endl;  //輸出都爲3
a.push_back(4);
cout<<a.back()<<endl;    //輸出爲4
a.pop_back();
cout<<a.back()<<endl;    //輸出爲3

pair

等價於有裏面兩種元素的結構體
pair 不需要頭文件

定義方式:pair<數據類型1,數據類型2> 變量名稱;
first, 第一個元素
second, 第二個元素
支持比較運算,以first爲第一關鍵字,以second爲第二關鍵字(字典序)
舉例:

pair<int,char> a;
a.first=1;
a.second=a;
cout<<a.first<<' '<<a.second<<endl;   //輸出1 a

string 字符串

char字符串的升級版。
需要頭文件#include <string>

定義方式:string 變量名稱;
size()/length() //返回字符串長度,這兩個等價,時間複雜度O(1)
empty() //返回是否爲空,是則返回true
clear() //清空該字符串
find() //查找某個字符或字符串,返回該字符串的開始下標
substr(起始下標,(子串長度)) //返回子串
c_str() //返回字符串所在字符數組的起始地址,即將一個string類型的字符串轉化爲char類型的字符串
[] //支持下標運算
支持加法操作與比較運算,按字典序
舉例:

string s;
s=(string)"abcd"+(string)"efgh";  //之後s爲"abcdefgh"
cout<<s.size()<<' '<<s.length()<<endl;  //都輸出8
cout<<s<<endl;    //輸出整個字符串"abcdefgh" 
for(int i=0;i<s.length();i++)   //與上面的等價
cout<<s[i];
cout<<endl;

//strlen()爲char類型的函數,所以直接strlen(s)會報錯
cout<<strlen(s.c_str())<<endl;   //但這樣就可以使用了,返回8
cout<<s.find("bc")<<endl;     //b的下標爲1,所以輸出1
cout<<s.substr(0,4)<<endl;    //開始位置爲s[0],長度爲4.輸出"abcd"
cout<<s.substr(4)<<endl;      //未規定長度,則默認爲最長
                              //開始位置爲s[4],一直到s[7].輸出"efgh"

stack 棧

維護一個數據結構:棧 的容器
需要頭文件#include <stack>

定義方式:stack<數據類型> 變量名稱;
size() //同上
empty() //同上
push() //向棧頂插入一個元素
top() //返回棧頂元素
pop() //彈出棧頂元素
舉例:

stack<int> st;
st.push(1);
st.push(2);
cout<<st.top()<<endl;   //輸出2
st.push(3);
cout<<st.top()<<endl;   //輸出3
st.pop();
cout<<st.top()<<endl;   //輸出2

queue 隊列

維護一個數據結構:隊列 的容器
需要頭文件:#include <queue>

定義方式:queue<數據類型> 變量名稱;
size() //同上
empty() //同上
push() //向隊尾插入一個元素
front() //返回隊頭元素
back() //返回隊尾元素
pop() //彈出隊頭元素
舉例:

queue<int> q;
q.push(1);
q.push(2);
q.push(3);
cout<<q.size()<<endl;   //輸出3
cout<<q.front()<<' '<<q.back()<<endl;   //輸出爲1 3
q.pop();
cout<<q.front()<<' '<<q.back()<<endl;   //輸出爲2 3

priority_queue 優先隊列(堆)

維護一個數據結構:堆 的容器
堆的特點(大/小根堆):堆頂元素保證爲堆中元素的最大/小值

需要的頭文件:#include <queue>
定義方式:priority_queue<數據類型> 變量名稱; (默認爲大根堆)
定義成小根堆的方式:priority_queue<int,vector<int>, greater<int> > q;
size() //同上
empty() //同上
push() //插入一個元素,時間複雜度O(log n)
top() //返回堆頂元素,O(1)
pop() //彈出堆頂元素,O(log n)
舉例:

以小根堆爲例
priority_queue<int,vector<int>,greater<int> > heap;
heap.push(1);
heap.push(2);
heap.push(3);
cout<<heap.top()<<endl;    //輸出最小值 1
heap.pop();    //彈出堆頂元素(1)
cout<<heap.top()<<endl;    //輸出最小值 2

deque 雙向隊列

可以看成一個雙向開口的數組,可以向兩端插入/刪除元素。
注意:雙向隊列的效率比較低(具體多低我也不知道),所以能不用盡量別用。
需要的頭文件:#include <deque>

定義方式:deque<數據類型> 變量名稱;
size() //同上
empty() //同上
clear() //同上
front()/back() //返回頭元素/尾元素
push_back()/pop_back() //向隊尾插入一個元素/刪除隊尾元素
push_front()/pop_front() //向隊頭插入一個元素/刪除隊頭元素
begin() //返回一個迭代器,它指向容器deque的第一個元素
end() //返回一個迭代器,它指向容器deque的最後一個元素的下一個位置
[] //支持下標運算
舉例:

這個就不舉例了,和上面的那些都差不多,而且deque也並不常用。

set/multiset/unordered_set

實現原理:set/multiset 基於平衡二叉樹(紅黑樹)
unordered_set 基於哈希表

該容器的特點:
set:自動排序、自動去重
multiset:自動排序、不去重
unordered_set:無序、自動去重
該類容器中的元素的值不可修改

需要的頭文件:
set/multiset:#include <set>
unordered_set:#include <unordered_set>
定義方式:set / multiset / unordered_set<數據類型> 變量名稱;
size() //同上
empty() //同上
clear() //同上
insert() //插入一個數
find() //查找一個數,返回迭代器的位置,未找到則返回end()
count() //返回某一個數的個數
erase() //(1) 輸入是一個數x,刪除所有x。O(k + logn) (2) 輸入一個迭代器,刪除這個迭代器
begin() //同上
end() //同上
下面的unordered_set沒有
lower_bound(x) //返回大於等於x的最小的數的迭代器
upper_bound(x) //返回大於x的最小的數的迭代器
set/multiset 增 刪 查 改 的效率爲O(log n)
unordered_set 增 刪 查 改 的效率爲O(1)

舉例:

以set爲例
set<int> a;
a.insert(1);
a.insert(3);
a.insert(2);
cout<<a.count(2)<<endl;  //輸出1
a.insert(2);
cout<<a.count(2)<<endl;  //因爲set自動去重,還是輸出1
注:遍歷set容器的方法只有用迭代器或者範圍for循環,這些後面會說

map/multimap/unordered_map 映射

將一種類型的變量與另一種類型的變量映射到一起。非常常用!(除了multimap)
實現原理:map/multimap 基於平衡二叉樹(紅黑樹)
unordered_map 基於哈希表

該容器的特點:
map:自動去重複、有序(不過對於map這一類來說,有沒有序/去不去重 一般沒什麼關係)
multimap:不去重、有序
unordered_map:無序、自動去重
該類容器中第一關鍵字的值不能修改。

需要的頭文件:
map/multimap:#include <map>
unordered_map:#include <unordered_map>
定義方式:map / multimap / unordered_map<數據類型1,數據類型2> 變量名稱;
size() //同上
empty() //同上
clear() //同上
insert() //插入的數是一個pair類型,它的兩個數據類型與map容器的兩個數據類型一致
erase() //輸入的參數是pair或者迭代器
count() //返回某一個數的個數
begin() //同上
end() //同上
不過對於map這一類來說,上面的那些都不重要!重要的是下面這個:
[] //注意multimap不支持此操作(這也是它不常用的原因)。 對於map時間複雜度是 O(logn),unordered_map是O(1)
舉例:
1 10 100 1000
字典

遍歷容器的幾種方法

一.範圍for循環

這是c++11中的一個新語句。它可以遍歷某個容器/數組中全部的元素。

以multiset爲例
multiset<int> a;
a.insert(1);
a.insert(5);
a.insert(3);
a.insert(2);
a.insert(4);
a.insert(1);
for(auto it:a)    //輸出爲1 1 2 3 4 5 
cout<<it<<' ';
二.迭代器

C++ 的 STL 爲每一種容器都定義了一種迭代器類型,迭代器是一種檢查容器內元素並遍歷元素的數據類型,C++ 中,對容器的訪問操作更趨向於是用迭代器而非下標操作,只有少數容器(如 vector)支持下標操作訪問容器元素。

迭代器類型可以用 * 操作符來訪問迭代器所指向的元素,以 *iter = 0 爲例,假設 it 指向 vector 對象 v 的第一個元素,那麼 *iter 與 v[0] 就是指向同一個元素,那麼 *iter = 0 就是將這個元素賦值爲 0,同數組類似,迭代器可以使用自增、自減操作符向前、向後移動迭代器指向容器中的下一個元素。

迭代器的常用操作:

  • *iter:對 iter 進行解引用,返回迭代器 iter 指向的元素的引用
  • iter->first:對 iter 進行解引用,獲取指定元素中名爲 first 的成員,等效於 (*iter).first
  • ++iter、iter++:給 iter 加 1,使其指向容器的下一個元素
  • –iter、iter–:給 iter 減 1,使其指向容器的前一個元素
  • iter1==iter2:比較兩個迭代器是否相等
  • iter1!=iter2:比較兩個迭代器是否不等

幾乎每種容器都定義了一對 begin()、end() 函數,用於返回相應的迭代器,如果容器中有元素的話,由 begin() 返回的迭代器指向第一個元素,而由 end() 返回的迭代器指向容器中最後一個元素的下一個位置,其沒有指向任何實際的元素,它只是起一個標誌的作用,表示已處理完容器中的所有元素。由於 end() 返回的迭代器不指向任何元素,因此不能對它進行解引用(*)或自增(++)操作。

以multiset爲例
multiset<int> a;
a.insert(1);
a.insert(5);
a.insert(3);
a.insert(2);
a.insert(4);
a.insert(1);
multiset<int>::iterator it;       //定義一個迭代器
for(it=a.begin();it!=a.end();it++)    //遍歷方法
cout<<*it<<' ';                           //輸出爲1 1 2 3 4 5 

//除了正向迭代器外,還有反向迭代器,二者唯一的區別在與反向迭代器會反向遍歷容器
multiset<int>::reverse_iterator rit;       //定義一個反向迭代器
for(rit=a.rbegin();rit!=a.rend();rit++)    //遍歷方法
cout<<*rit<<' ';                           //輸出爲5 4 3 2 1 1 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章