文章目錄
1、STL容器
1.1 介紹
容器分爲順序容器和關聯容器,這種劃分是基於容器中元素的組織方式。
容器名 | 中文名 | 頭文件 | 所屬概念 |
---|---|---|---|
vector | 向量 | <vector> | 隨機訪問容器,順序容器 |
deque | 雙端隊列 | <deque> | 隨機訪問容器,順序容器 |
list | 列表 | <list> | 可逆容器,順序容器 |
set | 集合 | <set> | 可逆容器,關聯容器 |
multiset | 多重集合 | <set> | 可逆容器,關聯容器 |
map | 映射 | <map> | 可逆容器,關聯容器 |
multimap | 多重映射 | <map> | 可逆容器,關聯容器 |
1.2 STL容器的共性
設S表示一種容器類型(例如vector),s1和s2都是S類型的實例,容器支持的基本功能如下
操作 功能
S s1
容器都有一個默認構造函數,用於構造一個沒有任何元素的空容器
s1 op s2
這裏的op是各種比較運算符,它會對兩個容器之間的元素按字典順序進行比較
s1.begin()
返回指向s1第一個元素的迭代器
s1.end()
返回指向s1最後一個元素的下一個位置的迭代器
s1.clear()
將容器s1的內容清空
s1.empty()
返回一個布爾值,容器爲空返回true,否則返回false
s1.size()
返回s1的元素個數
s1.swap(s2)
將s1容器和s2容器的內容交換
2、順序容器
2.1 介紹
STL中的順序容器包括向量(vector)、雙端隊列(deque)和列表(list),它們在邏輯上可看作一個長度可擴展的數組,容器中的元素都是線性排列。可人爲決定每個元素在容器中的位置,可以隨時向指定的位置插入新的元素和刪除已有的元素。
2.2 順序容器的共性
假設S表示容器的類型,s表示S類型的實例,用T表示S容器的元素類型,用t表示T類型的一個實例,用n表示一個整型數據,用p1和p2表示指向s中的元素的迭代器,用q1,q2表示任何一個指向T類型元素的輸入迭代器(未必指向S中的元素,也未必具有S::iterator類型),順序容器的基本功能如下所示:
- 1、構造函數
S s
使用默認構造函數,構造一個空容器
S s(n,t)
構造一個由n個t元素構成的容器實例s
S s(n)
構造一個有n個元素的容器實例s,每個元素都是T()
S s(q1,q2)
使用 [q1,q2) 區間內的數據作爲s的元素構造s
- 2、賦值函數
說明;
可以使用賦值函數assign將指定的元素賦給順序容器,
順序容器中原先的元素會被清除,賦值函數的3種形式是與構造函數一一對應的
s.assign(n,t)
賦值後的容器由n個t元素構成
s.assign(n)
賦值後的容器由n個值都爲T()的元素構成
s.assign(q1,q2)
賦值後的容器的元素爲 [q1,q2) 區間內的數據
- 3、元素的插入
說明:
向順序容器中可以一次插入一個或多個指定元素,
也可以將一個迭代器區間所表示的序列插入,
插入時需要通過一個指向當前容器元素的迭代器來指示插入位置。
s.insert(p1,t)
在s容器中p1所指向的位置插入一個新的元素t,
插入後的元素夾在原p1和p1-1所指向的元素之間,
該函數會返回一個迭代器指向新插入的元素
s.insert(p1,n,t)
在s容器中p1所指向的位置插入n個新的元素t,
插入後的元素夾在原p1和p1-1所指向的元素之間,沒有返回值
s.insert(p1,q1,q2)
將 [q1,q2) 區間內的元素順序插入到s容器中p1位置處,
新的元素夾在原p1和p1-1所指向的元素之間
- 4、元素的刪除
s1.erase(p1)
刪除s1容器中p1所指向的元素,返回被刪除元素的下一個元素的迭代器
s1.erase(p1,p2)
刪除s1容器中 [p1,p2) 區間內的元素,返回最後一個被刪除元素的下一個元素的
迭代器(即在刪除前p2所指向元素的迭代器)
- 5、改變容器的大小
s1.resize(n)
將容器的大小變爲n,如果原來的元素大於n,則容器末尾多餘的元素
會被刪除,如果原來的元素小於n,則在容器末尾會用T()填充
- 6、首尾元素的相關操作(高效)
s.front() 獲得容器首元素的引用
s.back() 獲得容器尾元素的引用
s.push_back(t) 向容器尾部插入元素t
s.pop_back() 將容器尾部的元素刪除
s.push_front(t) 向容器頭部插入元素t (向量除外)
s.pop_front() 將容器頭部的元素刪除 (向量除外)
3、關聯容器
3.1 介紹
對於關聯容器,它的每個元素都有一個鍵(key),容器中的元素的順序並不能人爲隨意決定,而是按照鍵的取值升序排列的。也就是說,對於一個關聯容器s,使用迭代器在 [s.begin(),s.end() )區間內遍歷,訪問到的序列總是升序的。
3.2 分類
按照容器中是否允許出現重複鍵值,關聯容器可分爲單重關聯容器和多重關聯容器:
- 單重關聯容器中的鍵值是唯一的,不允許重複,集合和映射屬於這一類;
- 多重關聯容器中,相同的鍵值允許重複出現,多重集合和多重映射屬於這一類。
按照鍵與元素的關係可以分爲簡單關聯容器和二元關聯容器:
- 簡單關聯容器以元素本身作爲鍵,集合和多重集合屬於這一類
- 二元關聯容器的元素是由鍵和某種類型的附加數據共同構成,鍵只是元素的一部分,映射和多重映射屬於這一類
3.3 二元組pair
二元關聯容器的元素類型是鍵類型和附加數據類型的組合,這種組合類型可以用一個二元組(pair)來表示,pair是頭文件中定義的結構體模板:
template<class T1,class T2>
struct pair{
T1 first; //二元組的第一元
T2 second; //二元組的第二元
pari(); //默認構造函數
pair(const T1 &x,const T2 &y); //構造first=x,second=y的二元組
template<class U,class V>pair(const pair<U,V>&p); //複製構造函數
};
3.4 關聯容器的共性
假設S表示容器的類型,s表示S類型的實例,用T表示S容器的元素類型,用t表示T類型的一個實例,用K表示S容器的鍵的類型,用k表示K的一個實例,用n表示一個整型數據,用p1和p2表示指向s中的元素的迭代器,用q1,q2表示任何一個指向T類型元素的輸入迭代器,關聯容器的基本功能如下所示:
- 1、構造函數
操作 | 功能 | 單重關聯容器 | 多重關聯容器 |
---|---|---|---|
S s | 構造一個空容器 | 構造一個空容器 | 構造一個空容器 |
S s(q1,q2) | 將[q1,q2)區間的數據作爲s的元素構造s | 當[q1,q2)範圍內出現具有相同鍵的元素時,只有一個元素會被加入s中 | [q1,q2)範圍內的所有元素均被無條件加入s中 |
- 2、元素的插入
操作 | 功能 | 單重關聯容器 | 多重關聯容器 |
---|---|---|---|
s.insert(t) | 將元素t插入s容器中 | 只有當不存在相同鍵的元素時才能成功插入,該函數返回類型爲pair<S::iterator,bool>。插入成功時,返回被插入元素的迭代器,否則返回與t的鍵相同的元素的迭代器和false | 插入總會成功,返回已插入元素的迭代器 |
s.insert(p1,t) | 將元素t插入s容器中,p1是一個提示的插入位置,如果提示位置準確(即t的鍵的大小剛好在p1-1和p1之間)則可以提高插入效率。即使提示位置不準確也可以正確完成插入操作,該函數總是返回一個迭代器 | 只有當不存在相同鍵的元素時才能成功插入,插入成功時,返回被插入元素的迭代器,否則返回與t的鍵相同的元素的迭代器 | 插入總會成功,返回已插入元素的迭代器 |
s.insert(q1,q2) | 相當於按順序對 [q1,q2) 區間內的每個元素x分別執行s.insert(x) | 略 | 略 |
- 3、元素的刪除
s.erase(p1) 刪除p1所指向的元素
s.erase(p1,p2) 刪除 [p1,p2) 區間內的元素
s.erase(k) 刪除所有鍵爲k的元素,返回被刪除元素的個數
- 4、鍵的查找和計數
s.find(k)
找到任意一個鍵爲k的元素,返回該元素的迭代器,如果s中沒有鍵爲k的元素,則返回s.end()
s.lower_bound(k)
得到s中第一個鍵值不小於k的元素的迭代器(第一個>=k的元素)
s.upper_bound(k)
得到s中第一個鍵值大於k的元素的迭代器(第一個>k的元素)
s.equal_range(k)
得到一個用pair<S::iterator,S::iterator>表示的區間,記爲 [p1,p2) 。
該區間剛好包含所有鍵值爲k的元素,p1==s.lower_bound(k)和p2==s.upper_bound(k)一定成立
s.count(k)
得到s容器中鍵爲k的元素個數
注:關聯容器的插入和刪除操作不會使任何已有的迭代器、指針或引用失效。
4、使用
1、stack
函數 | 原型 | 功能 |
---|---|---|
empty | bool empty() const | 判斷棧是否爲空,空返回true,否則返回false |
size | size_type size() const | 返回棧中元素的個數 |
top | T& top() ; const T& top() const | 返回棧頂元素 |
pop | void pop() | 出棧 |
push | void push(const T &x) | 入棧 |
2、queue
函數 | 原型 | 功能 |
---|---|---|
empty | bool empty() const | 判斷隊列是否爲空,空返回true,否則返回false |
size | size_type size() const | 返回隊列中元素的個數 |
front | T& front() ; const T& front() const | 返回隊頭元素 |
back | T& back ( ) ; const T& back ( ) const | 返回隊尾元素 |
pop | void pop() | 隊頭元素出隊 |
push | void push(const T &x) | 從隊尾入隊 |
3、priority_queue
函數 | 原型 | 功能 |
---|---|---|
empty | bool empty() const | 判斷優先隊列是否爲空,空返回true,否則返回false |
size | size_type size() const | 返回優先隊列中元素的個數 |
top | const T& top ( ) const | 返回優先級最高的元素 |
push | void push(const T &x) | 向優先隊列中添加元素 |
pop | void pop() | 優先級最高的元素出隊 |
由於優先隊列還涉及到優先級的設置,因此本文除了給出優先隊列的操作外,還對優先級的設置進行說明。
priority_queue類模板
template < class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
參數說明:
- T 說明優先隊列中元素的類型,可以是基本數據類型,也可以是用戶自定義數據類型
- Container 說明實現優先隊列的底層容器,默認是vector
- Compare 說明優先隊列的優先原則,即值大優先還是值小優先,特別注意此處實際表示的是!Compare。默認是less,less是一個表示值小優先的結構體的類模板,由!Compare可知優先隊列默認值大優先
設置優先原則的方法
情況一:元素爲用戶自定義數據類型
值小優先:重載<運算符爲大於含義
值大優先:重載<運算符爲小於含義
注:這樣重載是由於優先隊列的第三個參數實際表示的是!Compare的緣故
重載好後即可按如下方式定義:
priority_queue<T> que;
T爲自定義數據類型
情況二:元素爲基本數據類型
值小優先:使用與less相反的greater
示例:priority_queue<int,vector<int>,greater<int> >que
值大優先:優先隊列默認值大優先
示例:priority_queue<int> que
只有第一個參數,後面兩個參數使用默認值
4、vector
函數 | 功能 |
---|---|
rbegin() | 傳回一個逆向隊列的第一個數據。 |
rend() | 傳回一個逆向隊列的最後一個數據的下一個位置。 |
at(idx) | 傳回索引idx所指的數據,如果idx越界,拋出out_of_range。 |
capacity() | 返回容器中數據的個數。 |
max_size() | 返回容器能存放數據的最大數量。 |
operator[] | 返回容器中指定位置的一個引用。 |
5、list
函數 | 功能 |
---|---|
listl1(l2) | 複製 l2 |
it l.rbegin() | 返回“反向鏈表”的第1個元素的地址。即返回鏈表的最後一個元素的地址。 |
it l.rend() | 返回“反向鏈表”的最後一個元素的下一個位置,這麼說可能不正確,這個函數主要用於反向鏈表的操>作。返回的是地址,該地址沒有元素。 |
void l.remove (const value_type& val) | 刪除值等於val的元素,得一模一樣才能刪除,估計比對的是整塊內存的二進制。與erase不同。 |
void l.remove_if (Predicate pred) | 刪除元素。將鏈表中每個元素單獨傳入pred函數,只要返回的結果爲true,就刪除。pred不用加括>號,它類似於sort裏的comp |
void l.merge (list& x) | 將鏈表x接在l之後,合併爲一個鏈表l,合併完後鏈表x中的元素爲0了,但x仍存在。(不排序) |
void l.merge (list& x, Compare comp) | 將兩鏈表合併在一起,按照comp函數的排序規則來排序。 |
void l.sort() | 排序,按照默認的方法排序,一般爲增序,比如整數、字符串比較 |
void l.sort(comp) | 排序,按照comp函數所返回的那樣,若true則不改變位置,若false則交換位置。 |
void l.splice (it pos, list& x) | 將鏈表x中所有的元素“剪切”到pos處,其實只是指針操作,不用賦值 |
void l.splice (it pos, list& x, it i) | 將鏈表x中的元素i“剪切”到pos處,只是單個元素。 |
void l.splice (it pos, list& x, it first, it last) | 將鏈表x中first到last這段元素都遷移到l中的pos處。 |
void l.unique() | 刪除重複的多餘元素,使每個元素唯一。相同元素的第一個都不會刪。 |
void l.unique (Predicate pred) | 以pred函數爲依據,刪除重複的元素,當pred返回true時則刪除其中一個。 |
void l.reverse() | 將所有元素的順序置爲相反,比如升序變爲降序。 |
6、bitset
頭文件:<bitset>
1、構造函數:
bitset<4> b1;
無參構造,長度爲4,默認每一位爲0 :0000
bitset<8> b2(12);
長度爲8,二進制保存,前面用0補充 :00001100
string s = "100101";
bitset<10> b3(s);
長度爲10,前面用0補充 :0000100101
char s2[] = "10101";
bitset<13> b4(s2);
長度爲13,前面用0補充 :0000000010101
若參數的二進制表示比bitsize大,參數爲整數時取後面部分,參數爲字符串或字符數組時取前面部分
2、成員函數:
bs.any()
是否存在值爲1的二進制位
bs.none()
是否全部位爲0
bs.size()
位長
bs.count()
值爲1的個數
bs.test(pos)
測試pos處的二進制位是否爲1
bs.set()
全部位置1
bs.set(pos)
將pos位處的二進制位設置爲1
bs.reset()
全部位置0
bs.reset(pos)
pos位處的二進制位設置爲0
bs.flip()
全部位逐位取反
bs.flip(pos)
pos處的二進制位取反
bs.to_ulong()
將二進制轉換爲unsigned long輸出
bs.to_string()
將二進制轉換爲字符串輸出
~bs
按位取反
效果等效爲bs.flip()
os << b
將二進制位輸出到os流,小值在右,大值在左
3、位運算的使用:
>位運算符&、|、~、<<、>>可用於兩個bitset類型的實例。