STL源碼剖析(十五)關聯式容器之map、multimap

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