RB-tree是除AVl-tree之外被广泛应用的平衡二叉搜素树,AVL-tree是最早的平衡二叉树之一,在实际中应用的比较少,windows对进程地址空间的管理用到了AVL树,红黑树广泛应用在STL中,map和set都是用红黑树实现的。
AVL-tree是一种高度平衡的二叉搜素树,造成的结果是维护这种高度平衡所付出的代价比从中获得效率收益还高,所以在实际中应用不多,更多的是用追求局部而不是严格整体平衡的红黑树。本文将结合stl中rb_tree源码分析红黑树的一些结构。
RB-tree必须满足的规则:
1.每个节点不是红色就是黑色
2.根节点为黑色
3.如果节点为红,其子节点必须为黑
一般来说,我们不应使用rb_tree的iterators改变元素值,因为元素有其排列规则,虽然源代码阻止此事,因为rb_tree将为
set和map提供底层支持,而map运行元素的data被改变,只有key是不可以改变的
rb_tree提供两个insertion操作:insert_unique()和iinsert_equal()前者表示节点的key一定在整个tree中独一无二,否则出入失败,后者表示节点的key可重复
AVL-tree是一种高度平衡的二叉搜素树,造成的结果是维护这种高度平衡所付出的代价比从中获得效率收益还高,所以在实际中应用不多,更多的是用追求局部而不是严格整体平衡的红黑树。本文将结合stl中rb_tree源码分析红黑树的一些结构。
RB-tree必须满足的规则:
1.每个节点不是红色就是黑色
2.根节点为黑色
3.如果节点为红,其子节点必须为黑
4.任一节点到叶节点的任何路径,所含黑节点的树必须相同。
//rb_tree的定义
/*模板参数的含义:
1.key 表示节点的键
2.Value表示节点(key+value)
3.KeyOfValue表示怎么从key中取出value
4.Compare表示key的比较规则,应为要排序
5.Alloc分配器
*/
template <class key,class Value,class KeyOfValue,class Compare,class Alloc=alloc>
class rb_tree{
protected:
size_type node_count; //记录数的节点数量,占4个字节大小
link_type header; //头节点,指向root节点,类似于链表的头节点,它是一个指针,占4个字节
Compare key_compare; //节点的key比较规则,实际key_compare是一个函数,函数不占大小的,但实际上编译器在处理的时候会添加1个字节
//根据这里的分析,rb_tree占用的大小为9个字节,考虑对齐规则,rb_tree占用的大小为12字节,可以用sizeof(rb_tree)测试验证
protected:
typedef __rb_tree_node<Value> rb_tree_node;
...
public:
typedef rb_tree_node* link_type;
...
protected:
//获取节header的成员
link_type& root() const{
return (link_type&)header->parent;
}
link_type& leftmost() const{
return (link_type&)header->left;
}
link_type& rightmost() const{
return (link_type&)header->right;
}
//获取节点x的成员
static link_type& left(link_type x){
return (link_type&)x->left;
}
static link_type& right(link_type x){
return (link_type&)x->right;
}
static link_type& parent(link_type x){
return (link_type&)x->parent;
}
static reference value(link_type x){
return x->value_field;
}
static const Key& key(link_type x){
return KeyOfValue()(value(x));
}
static color_type& color(link_type x){
return (color_type&)(x->color);
}
...
public:
Compare key_comp() const{
return key_compare;
}
iterator begin(){
return leftmost();
}
iterator end(){
return header;
}
bool empty() const{
return node_count == 0;
}
size_type size() const{
return node_count;
}
size_type max_size() const{
return size_type(-1);
}
public:
//将x插入到RB-tree中,保持节点值独一无二
pair<iterator, bool> insert_unique(const value_type& x);
//将x插入到RB-tree中,允许节点值重复
iterator insert_equal(const value_type& x);
...
};
一般来说,我们不应使用rb_tree的iterators改变元素值,因为元素有其排列规则,虽然源代码阻止此事,因为rb_tree将为
set和map提供底层支持,而map运行元素的data被改变,只有key是不可以改变的
rb_tree提供两个insertion操作:insert_unique()和iinsert_equal()前者表示节点的key一定在整个tree中独一无二,否则出入失败,后者表示节点的key可重复
//测试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); //不会被插入
cout << itree.empty() << endl; //0
cout << itree.size() << endl; //5
cout << itree.count(5) << endl; //1
itree.insert_equal(5);
itree.insert_equal(5);
count << itree.size() << endl; //7
count << itree.count(5) << endl;//3