C++ STL标准库与泛型编程(五)红黑树、Set、Map

关联式容器,查找与元素的安插效率都很高,相当于一个小型的数据库(用 key 去寻找数据)。其底层实现是基于两个重要的技术:红黑树、散列表

Red - Black Tree 红黑树

一、相关概念

  1. rb_tree 是一种高度平衡搜索二叉树,其元素排列的规则有利于 search 和 insert,并同时保持适度的平衡。
  2. rb_tree 提供遍历操作以及 iterator。元素放入后有一定的排列规则,按正常规则(++ ite)迭代器遍历时为输出为排序状态(sorted)
  3.  不应使用 rb_tree 的 iterator 改变元素值(影响原有排序)。语法层面是不禁止这种操作的。如此设计的原因是,由 rb_tree 实现的 map 其 key 值(排序以 key 值为依据) 是不能改动的,而通过 iterator 改变 map 的 data 值是允许的
  4. rb_tree 提供两种 insertion 操作:insert_unique() 和 insert_equal()。 前者表示节点的 key 一定在整个 tree 中独一无二,否则安插失败(但不返回error,不做任何操作);后者表示节点的 key 可重复。

二、实现

Key 为 key 值的类型,Value 为放入的整个元素节点的数据类型、

KeyOfValue 为从 Value 中 取得 key 值的方法,此处应为一个函数对象、(例:identity<int>、select1st<value_type>)

Compare 为比较两个元素大小的函数对象。

 

//G2.9 测试 rb_tree
rb_tree<int,int,identity<int>,less<int>> itree;
cout << itree.empty() << endl;    //1
cout << itree.size() << endl;     //0

itree.insert_unique(3);
itree.insert_unique(8);
itree.insert_unique(5);
itree.insert_unique(9);
itree.insert_unique(13);
itree.insert_unique(5);    //no effect, since using insert_unique()
cout << itree.empty() << endl;    //0
cout << itree.size() << endl;    //5
cout << itree.count(5) << endl;    //1

itree.insert_equal(5);
itree.insert_equal(5);
cout << itree.size() << endl;    //7, since using insert_equal()
cout << itree.count(5) << endl;    //3

容器 set、multiset

一、相关概念

  1. set/multiset 以 rb_tree 为底层结构,因此有元素自动排序特性。排序的依據是 key,set/multiset 的 value 就是 key。
  2. set/multiset 提供遍历操作以及 iterator。元素放入后有一定的排列规则,按正常规则(++ ite)迭代器遍历时为输出为排序状态(sorted)
  3. 无法使用 set/multiset 的 iterator 改变元素值(因为 key 就是 value)。其 iterator 底层实现是 RBtree 的 const iterator,禁止对元素赋值。
  4. set 的元素不允许重复,所以 insert() 调用 insert_unique()。multiset 的元素可以重复,所以 insert() 调用 insert_equal()。

二、实现

  1. rep_type 说明了其底层实现为一个红黑树。其红黑树的5个模板参数都可由 set 的三个模板参数得来。
  2. 无法使用 set/multiset 的 iterator 改变元素值(key 就是 value),因为 set 的 iterator 是 const 不允许通过它改变元素。
  3. set 的所有操作都转调用底层 t 的类方法

容器 Map、Multimap

一、相关概念

  1. map/multimap 以 rb_tree 为底层结构,因此有元素自动排序特性。排序的依据是 key。
  2. key 不能修改,data 可以修改。map/multimap 内部自动将 user 指定的 key type 设为 const,如此便能禁止 user 对 key 的赋值。

二、实现

 select1st<pair<const int, string>> 从 Value 中 取得 key 值的方法,即取 pair 中的第一个类型 int 作为 key。

map 的 iterator 就是 rb_tree 的迭代器。其中 pair 的第一个模板参数为 const int。

map 独有的 operator [ ]

  • Allows for easy lookup with the subscript (@c[ ])
  • operator. Returns data asscoiated with the key specified
  • subscript. If the key does not exist, a pair with that key
  • is created using default values, which is then returned.

如果 key 值不存在,则生成一个带有默认 data 值的 value安插进去

lower_bound() 是二分查找的一种,试图在排序过的元素中寻找 value 。若查找范围内拥有与 value 相等的元素(s),便返回一个 iterator 指向其中第一个元素。如果没有这样的元素存在,便返回“假设该元素存在是应该出现的位置”。也就是说它会返回 iterator 指向第一个不小于 value 的元素。如果 value 大于查找范围内的任何元素,将返回 last 。换句话说,lower_bound 返回的是“不破坏排序得以安插 value 的第一个适当位置”。

而 operator [ ] 最终返回的是这个位置的 .second引用,可以利用这个引用直接赋值,相当于 insert() 操作 。

 

猜你喜欢

转载自blog.csdn.net/SimonxxSun/article/details/85264200
今日推荐