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); }
发布了107 篇原创文章 · 获赞 197 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/weixin_42462202/article/details/102239562