目录
容器rb_tree
Red-Black tree(红黑树)是平衡二叉搜索树(balanaced binary search tree)中常被使用的一种。平衡二叉搜索树的特征:排列规则有利于search和insert,并保持适度平衡——无任何节点过深。
rb_tree提供遍历操作及iterators。按正常规则(++ite)遍历,便能获得排序状态。
我们不应使用rb_tree的iterators改变元素值(因为元素有其排列规则)。编程层面并未阻值此事。如此设计是正确的,因为rb_tree即将为set和map服务(作为其底部支撑),而map允许元素的data被改变,只有元素的key才是不可被改变的。
rb_tree提供两种insert操作:insert_unique()和insert_equal()前者表示节点的key一定在整个tree中独一无二,否则安装失败,后者表示节点的key可以重复。
rb_tree的实现代码
namespace rb_tree{ template <class Key, //键 class Value, //key与data组合称为data class KeyOfValue, //如何从value中取出data class Compare, //key之间的比较方法 class Alloc = alloc> //分配器 class rb_tree { protected: typedef __rb_tree_node<Value> rb_tree_node; public: typedef rb_tree_node* link_type; protected: //RB_tree只以三个资料表现它自己 size_type node_count; //rb_tree的大小 4 link_type header; //大小为4 Compare key_compaer; //key的比较规则,应该是仿函数对象 大小为1 }; };
rb_tree的结构
rb_tree的noede结构
_M_color: _Rb_tree_color //节点颜色 枚举类型 _M_parent: _Base_Ptr //指向父节点的指针 _M_right: _Base_Ptr //指向右孩子的指针 _M_right: _Base_ptr //指向左孩子的指针
所以一共是16个字节
set/multiset
set的定义
set/multiset是以rb-tree为底层结构,因此元素有自动排序的性质。排序的依据是key,而set/multiset元素的key和value合二为一。
set/multiset提供遍历操作,以及iterators.按照正常操作就可以获得排序状态。
我们无法使用set/multiset的iterators改变元素的值(因为key有其严谨的排序规则)。set/multiset的iterator是其改变底部RB-tree的const iterator,就是为了禁止user对元素赋值。
set元素的key独一无二,因此其insert()用的是rb_tree的insert_unique();
multiset的key可以重复,因此insert()用的是rb_tree的insert_equal();
set的代码实现
namespace set_test { template <class Key, class Compare = less<Key>, class Alloc = alloc> class set { public: //typedefs typedef Key key_type; typedef Key value_type; typedef Compare key_compare; typedef Compare value_compare; private: typedef rb_tree<key_type, value_type, identity<value_type>, key_compare, Alloc>rep_type; rep_type t; public: typedef typename rep_type::const_iterator iterator; }; }
set的操作分析
当你拿set的迭代器时,拿到的是const_iterator,而且是rb_tree的迭代器,所以set不允许通过迭代器改变key.
set的所有操作都是通过调用底部的rb_tree来完成的,和stack和queue一样(调用deque)
set内部数据结构图
map/multimap
map的性质
map/multimap是以rb_tree为底层结构,因此有元素自动排序特性,排序的依据是key.
map/multimap提供遍历操作以及iterators,按正常规则遍历,便能获得排序状态。
我们无法使用map/multimap的iterators改变元素的key,但可以用它来改变元素的data,因此map/multimap内部自动将user指定的 key type设为const,如此便能禁止user对元素的key赋值。
map元素的key必须独一无二,因此insert使用的是rb_tree的insert_unique()
multimap的key是可以重复的,因此insert使用的是rb_tree的insert_equal()
map的实现
#pragma once template <class Key, class T,class Compare = less<key>,class Alloc = alloc> class map { public: typedef Key key_type; typedef T data_type; typedef T mapped_type; typedef pair<const Key, T> value_type; typedef Compare key_compare; private: typedef rb_tree<key_type, value_type, selectlst<value_type>, key_compare, Alloc> rep_type; rep_type t; public: typedef typename rep_type::iterator iterator; };
map的内部数据结构图
map数据结构的组成
map<int,string>imap; 当我们输入上述代码时: pair<const key,T>value_type; 将传入的两个参数合并成为一个map,且pair的第一个元素为const.
来源:https://www.cnblogs.com/ccpang/p/12271912.html