1. 程式人生 > 其它 >【C++】map和set

【C++】map和set

技術標籤:C++資料結構c++演算法mapset

文章目錄

1.關聯式容器

我們已經接觸過STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,這些容器統稱為序列式容器,因為其底層為線性序列的資料結構,裡面儲存的是元素本身。那什麼是關聯式容器?它與序列式容器有什麼區別?

關聯式容器也是用來儲存資料的,與序列式容器不同的是,其裡面儲存的是<key, value>結構的鍵值對,在資料檢索時比序列式容器效率更高。

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文件介紹
大致總結為以下幾點:

  1. set是按照一定次序儲存元素的容器;
  2. 在set中,元素的value也標識它(value就是key,型別為T),並且每個value必須是唯一的。set中的元素不能在容器中修改(元素總是const),但是可以從容器中插入或刪除它們;
  3. 在內部,set中的元素總是按照其內部比較物件(型別比較)所指示的特定嚴格弱排序準則進行排序;
  4. set容器通過key訪問單個元素的速度通常比unordered_set容器慢,但它們允許根據順序對子集進行直接迭代;
  5. 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文件
大致總結為以下幾點:

  1. map是關聯容器,它按照特定的次序(按照key來比較)儲存由鍵值key和值value組合而成的元素;
  2. 在map中,鍵值key通常用於排序和惟一地標識元素,而值value中儲存與此鍵值key關聯的內容。鍵值key和值value的型別可能不同,並且在map的內部,key與value通過成員型別value_type繫結在一起,為其取別名稱為pair:typedef pair value_type;
  3. 在內部,map中的元素總是按照鍵值key進行比較排序的;
  4. map中通過鍵值訪問單個元素的速度通常比unordered_map容器慢,但map允許根據順序對元素進行直接迭代(即對map中的元素進行迭代時,可以得到一個有序的序列);
  5. map支援下標訪問符,即在[]中放入key,就可以找到與key對應的value;
  6. 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文件介紹
大致總結為以下幾點:

  1. multiset是按照特定順序儲存元素的容器,其中元素是可以重複的;
  2. 在multiset中,元素的value也會識別它(因為multiset中本身儲存的就是<value, value>組成的鍵值對,因此value本身就是key,key就是value,型別為T). multiset元素的值不能在容器中進行修改(因為元素總是const的),但可以從容器中插入或刪除;
  3. 在內部,multiset中的元素總是按照其內部比較規則(型別比較)所指示的特定嚴格弱排序準則進行排序;
  4. multiset容器通過key訪問單個元素的速度通常比unordered_multiset容器慢,但當使用迭代器遍歷時會得到一個有序序列;
  5. 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文件介紹
大致總結為以下幾點:

  1. Multimaps是關聯式容器,它按照特定的順序,儲存由key和value對映成的鍵值對<key, value>,其中多個鍵值對之間的key是可以重複的;
  2. 在multimap中,通常按照key排序和惟一地標識元素,而對映的value儲存與key關聯的內容。key和value的型別可能不同,通過multimap內部的成員型別value_type組合在一起,value_type是組合key和value的鍵值對:typedef pair<const Key, T> value_type;
  3. 在內部,multimap中的元素總是通過其內部比較物件,按照指定的特定嚴格弱排序標準對key進行排序的;
  4. multimap通過key訪問單個元素的速度通常比unordered_multimap容器慢,但是使用迭代器直接遍歷multimap中的元素可以得到關於key有序的序列;
  5. multimap在底層用二叉搜尋樹(紅黑樹)來實現。

3.4.2 multimap的使用

multimap中的介面可以參考map,功能都是類似的。