STL源碼剖析(十五)關聯式容器之map、multimap
文章目錄
map 和 multimap 每個元素都是一個對組,有 key 也有 dada
map 和 multimap 的主要區別是,map 鍵值不可以重複,multimap 可以
一、map、multimap的數據結構
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:
typedef Key key_type;
typedef T data_type;
typedef pair<const Key, T> value_type;
...
private:
typedef rb_tree<key_type, value_type,
select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing map
...
};
map 的成員函數只有一棵紅黑樹,基本上所有的操作依賴於它,要搞懂 map 的數據結構,首先需要先弄懂指定給紅黑樹的這些模板參數
紅黑樹的模板參數定義如下
template <class Key, class Value, class KeyOfValue, class Compare,
class Alloc = alloc>
class rb_tree {
...
};
-
Key表示鍵值,在 map 的模板參數指定
-
Vlue表示鍵值加上數據,在 map 中這樣定義 typedef pair<const Key, T> value_type,其中的 pair 爲對組,負責將兩個類型結合成一個類型,其定義如下
template <class T1, class T2> struct pair { typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair(const T1& a, const T2& b) : first(a), second(b) {} };
first 獲取第一個元素,second 獲取第二個元素
仔細看可以 pair 指定的 Key 爲 const Key,表示 key 值是不可以被修改的
-
KeyOfValue 是從 value 中獲取 key 的仿函數,在 map 中定義如下,select1st<value_type>,其實就是取對組的 first 成員,定義如下
template <class Pair> struct select1st : public unary_function<Pair, typename Pair::first_type> { const typename Pair::first_type& operator()(const Pair& x) const { return x.first; } };
-
Compare 用於鍵值比較的仿函數,map 默認指定的是 less<Key>
到這裏,map 的數組結構也應該清楚了,multimap 的數據結構其實是和 map 一樣的,這裏就不列出了
二、map、multimap的迭代器
map 和 multimap 的迭代器都是一樣的,都是直接取出紅黑樹的迭代器,如下
typedef rb_tree<key_type, value_type,
select1st<value_type>, key_compare, Alloc> rep_type;
typedef typename rep_type::iterator iterator;
如果要通過迭代器修改某個節點的數據,需要下面這樣做
it->second = xxx;
三、map、multimap的操作
map 和 multimap 的操作基本相同,都是調用紅黑樹,唯一的區別就是插入操作調用紅黑樹不同的插入函數
3.1 構造函數
默認構造
map() : t(Compare()) {}
初始化紅黑樹
拷貝構造
map(const map<Key, T, Compare, Alloc>& x) : t(x.t) {}
拷貝紅黑樹
3.2 析構函數
map 和 multimap 沒有定義析構函數,當釋放內存的時候,其中的紅黑樹會自動被析構釋放掉
3.3 插入元素
map 插入元素
pair<iterator,bool> insert(const value_type& x) { return t.insert_unique(x); }
調用的是紅黑樹的 insert_unique 方法,其不允許鍵值重複
multimap 插入元素
iterator insert(const value_type& x) { return t.insert_equal(x); }
調用的是紅黑樹的 insert_equal 方法,其運行鍵值重複
3.4 刪除元素
size_type erase(const key_type& x) { return t.erase(x); }
通過紅黑樹的 erase 方法刪除
3.5 其他操作
begin
iterator begin() { return t.begin(); }
end
iterator end() { return t.end(); }
find
根據 key 查找指定節點,放回對應的迭代器
iterator find(const key_type& x) { return t.find(x); }
**lower_bound **
查找大於等於指定 key 的節點
iterator lower_bound(const key_type& x) {return t.lower_bound(x); }
**upper_bound **
查找大於指定 key 的節點
iterator upper_bound(const key_type& x) {return t.upper_bound(x); }