【C++】map和set
文章目錄
1.關聯式容器
我們已經接觸過STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,這些容器統稱為序列式容器,因為其底層為線性序列的資料結構,裡面儲存的是元素本身。那什麼是關聯式容器?它與序列式容器有什麼區別?
2.鍵值對
用來表示具有一一對應關係的一種結構,該結構中一般只包含兩個成員變數key和value,key代表鍵值,value表示與key對應的資訊。比如:現在要建立一個英漢互譯的字典,那該字典中必然有英文單詞與其對應的中文含義,而且,英文單詞與其中文含義是一一對應的關係,即通過該應該單詞,在詞典中就可以找到與其對應的中文含義。
SGI-STL中關於鍵值對的定義:
template <class T1, class T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
T1 first;
T2 second;
pair(): first(T1()), second(T2())
{}
pair(const T1& a, const T2& b): first(a), second(b)
{}
};
3. 樹形結構的關聯式容器
根據應用場景的不桶,STL總共實現了兩種不同結構的管理式容器:樹型結構與雜湊結構。樹型結構的關聯式容器主要有四種:map、set、multimap、multiset。這四種容器的共同點是:使用平衡搜尋樹(即紅黑樹)作為其底層結果,容器中的元素是一個有序的序列。下面一依次介紹每一個容器。
3.1 set
3.1.1 set的介紹
set文件介紹
大致總結為以下幾點:
- set是按照一定次序儲存元素的容器;
- 在set中,元素的value也標識它(value就是key,型別為T),並且每個value必須是唯一的。set中的元素不能在容器中修改(元素總是const),但是可以從容器中插入或刪除它們;
- 在內部,set中的元素總是按照其內部比較物件(型別比較)所指示的特定嚴格弱排序準則進行排序;
- set容器通過key訪問單個元素的速度通常比unordered_set容器慢,但它們允許根據順序對子集進行直接迭代;
- set在底層是用二叉搜尋樹(紅黑樹)實現的。
3.1.2 set的使用
1.set的模板引數列表
T: set中存放元素的型別,實際在底層儲存<value, value>的鍵值對
Compare:set中元素預設按照小於來比較
Alloc:set中元素空間的管理方式,使用STL提供的空間配置器管理
2.set的構造
set (const Compare& comp = Compare(), const Allocator& =
Allocator() );//構造空的set
set (InputIterator first, InputIterator last, const Compare&
comp = Compare(), const Allocator& = Allocator() );//用[first, last)區間中的元素構造set
set ( const set<Key,Compare,Allocator>& x);//set的拷貝構造
3.set的迭代器
iterator begin() //返回set中起始位置元素的迭代器
iterator end() //返回set中最後一個元素後面的迭代器
const_iterator cbegin() const //返回set中起始位置元素的const迭代器
const_iterator cend() const //返回set中最後一個元素後面的const迭代器
reverse_iterator rbegin() //返回set第一個元素的反向迭代器,即end
reverse_iterator rend() //返回set最後一個元素下一個位置的反向迭代器,即rbegin
const_reverse_iterator crbegin() const //返回set第一個元素的反向const迭代器,即cend
const_reverse_iterator crend()const//返回set最後一個元素下一個位置的反向const迭代器,即crbegin
4.set的容量
bool empty ( ) const 檢測set是否為空,空返回true,否則返回true
size_type size() const 返回set中有效元素的個數
5.set修改操作
pair<iterator,bool> insert (const value_type& x )//在set中插入元素x,實際插入的是<x, x>構成的鍵值對,如果插入成功,返回<該元素在set中的位置true>,如果插入失敗,說明x在set中已經存在,返回<x在set中的位置,false>
void erase ( iterator position ) //刪除set中position位置上的元素
size_type erase ( const key_type& x ) //刪除set中值為x的元素,返回刪除的元素的個數
void erase ( iterator first,iterator last ) //刪除set中[first, last)區間中的元素
void swap (set<Key,Compare,Allocator>&st );//交換set中的元素
void clear ( ) //將set中的元素清空
iterator find ( constkey_type& x ) const //返回set中值為x的元素的位置
size_type count ( const key_type& x ) const //返回set中值為x的元素的個數
3.2 map
3.2.1 map的介紹
map文件
大致總結為以下幾點:
- map是關聯容器,它按照特定的次序(按照key來比較)儲存由鍵值key和值value組合而成的元素;
- 在map中,鍵值key通常用於排序和惟一地標識元素,而值value中儲存與此鍵值key關聯的內容。鍵值key和值value的型別可能不同,並且在map的內部,key與value通過成員型別value_type繫結在一起,為其取別名稱為pair:typedef pair value_type;
- 在內部,map中的元素總是按照鍵值key進行比較排序的;
- map中通過鍵值訪問單個元素的速度通常比unordered_map容器慢,但map允許根據順序對元素進行直接迭代(即對map中的元素進行迭代時,可以得到一個有序的序列);
- map支援下標訪問符,即在[]中放入key,就可以找到與key對應的value;
- map通常被實現為二叉搜尋樹(更準確的說:平衡二叉搜尋樹(紅黑樹))。
3.2.2 map的使用
1.map的模板引數說明
key: 鍵值對中key的型別
T: 鍵值對中value的型別
Compare: 比較器的型別,map中的元素是按照key來比較的,預設情況下按照小於來比較,一般情況下(內建型別元素)該引數不需要傳遞,如果無法比較時(自定義型別),需要使用者自己顯式傳遞比較規則(一般情況下按照函式指標或者仿函式來傳遞)
Alloc:通過空間配置器來申請底層空間,不需要使用者傳遞,除非使用者不想使用標準庫提供的空間配置器
注意:在使用map時,需要包含標頭檔案。
2.map的構造
map() //構造一個空的map
3.map的迭代器
begin()和end() //begin:首元素的位置,end最後一個元素的下一個位置
cbegin()和cend() //與begin和end意義相同,但cbegin和cend所指向的元素不能修改
rbegin()和rend() //反向迭代器,rbegin在end位置,rend在begin位置,其++和--操作與begin和end操作移動相反
crbegin()和crend() //與rbegin和rend位置相同,操作相同,但crbegin和crend所指向的元素不能修改
4.map的容量與元素訪問
bool empty ( ) const //檢測map中的元素是否為空,是返回true,否則返回false
size_type size() const //返回map中有效元素的個數
mapped_type& operator[] (const key_type& k) //返回去key對應的value
5.map中元素的修改
pair<iterator,bool> insert (const value_type& x )//在map中插入鍵值對x,注意x是一個鍵值對,返回值也是鍵值對:iterator代表新插入元素的位置,bool代表釋放插入成功
void erase ( iterator position ) //刪除position位置上的元素
size_type erase ( const key_type& x ) //刪除鍵值為x的元素
void erase ( iterator first,iterator last ) //刪除[first, last)區間中的元素
void swap (map<Key,T,Compare,Allocator>&mp )//交換兩個map中的元素
void clear ( ) //將map中的元素清空
iterator find ( const key_type& x)//在map中插入key為x的元素,找到返回該元素的位置的迭代器,否則返回end
const_iterator find ( const key_type& x ) const//在map中插入key為x的元素,找到返回該元素的位置的const迭代器,否則返回cend
size_type count ( const key_type& x ) const//返回key為x的鍵值在map中的個數,注意map中key是唯一的,因此該函式的返回值要麼為0,要麼為1,因此也可以用該函式來檢測一個key是否在map中
3.3 multiset
3.3.1 multiset的介紹
multiset文件介紹
大致總結為以下幾點:
- multiset是按照特定順序儲存元素的容器,其中元素是可以重複的;
- 在multiset中,元素的value也會識別它(因為multiset中本身儲存的就是<value, value>組成的鍵值對,因此value本身就是key,key就是value,型別為T). multiset元素的值不能在容器中進行修改(因為元素總是const的),但可以從容器中插入或刪除;
- 在內部,multiset中的元素總是按照其內部比較規則(型別比較)所指示的特定嚴格弱排序準則進行排序;
- multiset容器通過key訪問單個元素的速度通常比unordered_multiset容器慢,但當使用迭代器遍歷時會得到一個有序序列;
- multiset底層結構為二叉搜尋樹(紅黑樹)。
3.3.2 multiset的使用
#include <set>
void TestSet()
{
int array[] = { 2, 1, 3, 9, 6, 0, 5, 8, 4, 7 };
// 注意:multiset在底層實際儲存的是<int, int>的鍵值對
multiset<int> s(array, array + sizeof(array)/sizeof(array[0]));
for (auto& e : s)
cout << e << " ";
cout << endl;
return 0;
}
其他介面介面與set相同,可參考set。
3.4 multimap
3.4.1 multimap的介紹
multimap文件介紹
大致總結為以下幾點:
- Multimaps是關聯式容器,它按照特定的順序,儲存由key和value對映成的鍵值對<key, value>,其中多個鍵值對之間的key是可以重複的;
- 在multimap中,通常按照key排序和惟一地標識元素,而對映的value儲存與key關聯的內容。key和value的型別可能不同,通過multimap內部的成員型別value_type組合在一起,value_type是組合key和value的鍵值對:typedef pair<const Key, T> value_type;
- 在內部,multimap中的元素總是通過其內部比較物件,按照指定的特定嚴格弱排序標準對key進行排序的;
- multimap通過key訪問單個元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍歷multimap中的元素可以得到關於key有序的序列;
- multimap在底層用二叉搜尋樹(紅黑樹)來實現。
3.4.2 multimap的使用
multimap中的介面可以參考map,功能都是類似的。