C++語言:STL

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,默認每一位爲00000

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類型的實例。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章