Loading

关联式容器

容器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.
posted @ 2020-02-08 16:07  三只猫-  阅读(237)  评论(0编辑  收藏  举报