红黑树RB_tree

   红黑树也是一种而叉搜索树,因此二叉搜索树的性质红黑树都具有,同时,我们知道为了避免最坏情况下的二叉搜索树(就是高度不平衡的情况)衍生出了AVL树,使其任何节点的左右子树的高度差相差最多1,从而达到平衡,以确保最坏情况下的搜索效率。当然红黑树为了比较好的搜索效率降低了对平衡的要求,但是红黑树仍然具有良好的平衡状态。

    AVL树与RB_tree

    AVL树也称为高度平衡树,其插入,删除,查找在平均和最坏情况下都是O(log n),增加和删除要通过一次或多次树的旋转来重新平衡这个树。

    RB_tree并不追求完全平衡,只要求部分达到平衡要求,降低了对旋转的要求,从而提高了性能,红黑树能够以O(log 2 n)的时间复杂度进行插入,删除,查找,此外由于它的设计任何不平衡都会在3次旋转之内解决。相比较而言红黑树和AVL树的算法时间复杂度相同,但统计性能比AVL树高。同时,红黑树的应用比AVL树广泛

    例如:(1)红黑树广泛应用于c++的STL中,比如关联式容器set, map,multiset, multimap都以RB_tree为底层机制。

               (2)epoll在内核中的实现,用红黑树管理事件块。

               (3)linux进程调度上,用红黑树管理进程控制块。

               (4)nginx中用红黑树管理timer

下面自己分析了SGI中的stl_tree.h源码的分析

#ifndef __SGI_STL_INTERNAL_TREE_H
#define __SGI_STL_INTERNAL_TREE_H
//RB-tree的节点设计
//设计思路节点设计分为两层__rb_tree_node继承__rb_tree_node_base以达到将指针和数据分开
typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red = false;
const __rb_tree_color_type __rb_tree_black = true;

struct __rb_tree_node_base
{
    typedef __rb_tree_color_type color_type;
    typedef __rb_tree_node_base* base_ptr;
    color_type color;
    base_ptr parent;
    base_ptr left;
    base_ptr right;
    //找到存储的最小值
    static base_ptr minimum(base_ptr x)
    {
        wile(x->left != 0){
            x = x->left;
        }
        return x;
    }
    static base_ptr maximum(base_ptr x)
    {
        while(x->right != 0){
            x = x->right;
        }
        return x;
    }
};

template<class Value>
struct __rb_tree_node : public __rb_tree_node_base
{
    typedef __rb_tree_node<Value>* link_type;
    Value value_field;
};

//因为红黑树是非线性的结构,所以要找到一个节点的前面的节点或者后面的节点比较麻烦,且红黑树节点的显示是

//按中序排列的,所以对迭代器的前进和后退操作要借用内置函数increment()和decrement()

//RB_tree迭代器结构设计,也是采用双层迭代其结构
struct __rb_base_iterator
{
    typedef __rb_tree_node_base::base_ptr base_ptr;
    typedef bidirectional_iterator_tag iterator_category;
    typedef ptrdiff_t difference_type;
    base_ptr node;
    //迭代器的前进操作operator++()调用了基层迭代器的increment()
    //(1)如果node有右子树,但这个右子树没有左子节点,那么node前进一个节点为node->right.如果这个右子   树有左子树,那么node后面的节点就是这个左子树的最左边的那个节点。
    //(2)如果node没有右子树,并且node是node->parent的左子树,那么node后面的节点是node->parent。如果node是node->parent的右子树,则一直上朔,直到不再是右子节点比如为y,那么node后面的节点是就是y->parent这个节点

    void increment()
    {
        if(node->right != 0){
            node = node->right;
            while(node->left != 0){
                node = node->left;
            }
        }
        else{
            base_ptr y = node->parent;
            while(node == y->right){
                node = y;
                y = y->parent;
            }
            if(node->right != y){
                node = y;
            }
        }
    }
    //迭代器的后退操作operator--()调用基层迭代器ecrement()
    //(1)node有左子树,且node的左子树没有右子树,那么node前面的节点就是node->left。如果node的左子树有右子树,那么node前面的节点就是这个右子树的最右边的节点。
    //(2)node没有左子树,且node为其父节点的左节点,那么就上朔直到node不为node->parent的左节点,那么node的前面的节点就是这个node->parent。如果为其父节点的右节点,那么node的前面的节点就是node->parent。

    void decrement()
    {
       //判断node就是header这个虚节点
        if(node->color == __rb_tree_red && node->parent->parent == node){
            node = node->right;
        }
        else if(node->left != 0){
            base_ptr y = node->left;
            while(y->right != 0){
                y = y->right;
            }
            node = y;
        }
        else{
            base_ptr y = node->parent;
            while(node == y->left){
                node = y;
                y = y->parent;
            }
            node = y;
        }  
    }
};

template<calss Value, class Ref, class Ptr>
struct __ rb_tree_iterator : public __rb_tree_base_iterator
{
     typedef Value value_type;
     typedef Ref reference;
     typedef Ptr pointer;
     typedef __rb_tree_iterator<Value, Value&, Value*>             iterator;
     typedef __rb_tree_iterator<Value, const Value&, const Value*> const_iterator;
     typedef __rb_tree_iterator<Value, Ref, Ptr>                   self;
     typedef __rb_tree_node<Value>* link_type;

    __rb_tree_iterator(){}
    __rb_tree_iterator(link_type x){node = x;}
    __rb_tree_iterator(const iterator& it){ode = it.node;}

    self& operator++() { increment(); return *this; }
    self operator++(int) {
        self tmp = *this;
        increment();
        return tmp;
    }
    
    self& operator--() { decrement(); return *this; }
    self operator--(int) {
        self tmp = *this;
        decrement();
        return tmp;
    }
};

inline bool operator==(const __rb_tree_base_iterator& x,
                       const __rb_tree_base_iterator& y)
{
   return x.node == y.node;
}

inline bool operator!=(const __rb_tree_base_iterator& x,
                       const __rb_tree_base_iterator& y)
{
   return x.node != y.node;
}
//RB_tree数据结构
template <class Key, class Value, class KeyOfValue, class Compare,
          class Alloc = alloc>
class rb_tree {
protected:
  typedef void* void_pointer;
  typedef __rb_tree_node_base* base_ptr;
  typedef __rb_tree_node<Value> rb_tree_node;
  typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator;
  typedef __rb_tree_color_type color_type;
public:
  typedef Key key_type;
  typedef Value value_type;
  typedef value_type* pointer;
  typedef const value_type* const_pointer;
  typedef value_type& reference;
  typedef const value_type& const_reference;
  typedef rb_tree_node* link_type;
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;
public:
    rb_tree(const Compare& comp = Compare())
    : node_count(0), key_compare(comp) { init(); }

    ~rb_tree() {
        clear();
        put_node(header);
    }
    rb_tree<Key, Value, KeyOfValue, Compare, Alloc>&
    operator=(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x);
protected:
    get_node(){return rb_tree_node_allocator::allocate();}
    void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }

    link_type create_node(const value_type& x) {
        link_type tmp = get_node();
        put_node(tmp);
        return tmp;
    }
    //复制一个节点
    link_type clone_node(link_type x) {
        link_type tmp = create_node(x->value_field);
        tmp->color = x->color;
        tmp->left = 0;
        tmp->right = 0;
        return tmp;
    }

    void destroy_node(link_type p) {
        destroy(&p->value_field);
        put_node(p);
    }

protected:
    size_type node_count; // keeps track of size of tree
    link_type header;  
    Compare key_compare;
    //这三个函数方便取得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的成员(自身做参数)自己对这12个函数没有具体搞明白为什么写两种
    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); }
    //这六个函数方便取得节点x的成员(以父类类型的节点做参数)
    static link_type& left(base_ptr x) { return (link_type&)(x->left); }
    static link_type& right(base_ptr x) { return (link_type&)(x->right); }
    static link_type& parent(base_ptr x) { return (link_type&)(x->parent); }
    static reference value(base_ptr x) { return ((link_type)x)->value_field; }
    static const Key& key(base_ptr x) { return KeyOfValue()(value(link_type(x)));}
    static color_type& color(base_ptr x) { return (color_type&)(link_type(x)->color); }

    static link_type minimum(link_type x) {
      return (link_type)  __rb_tree_node_base::minimum(x);
    }
    static link_type maximum(link_type x) {
      return (link_type) __rb_tree_node_base::maximum(x);
    }

public:
    typedef __rb_tree_iterator<value_type, reference, pointer> iterator;
    typedef __rb_tree_iterator<value_type, const_reference, const_pointer>
          const_iterator;

public:
    Compare key_comp()const {return key_compare;}
    iterator begin(){return leftmost;}
    //最后的一个节点应该是rightmost但是end()指向的是最后节点的后一个节点自然就是header
    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:
    pair<iterator, bool>insert_unique(const value_type& x);
    iterator insert_equal(const value_type& x);
    iterator insert_unique(iterator position, const value_type& x);
    iterator insert_equal(iterator position, const value_type& x);

};
//这里的返回值是个RB_tree迭代器,所以前面加那么多
template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_equal(const value& v)
{
    link_type y = header;
    link_type x = root();
    while(x != 0){
        y = x;
        x = key_compare(KetOfValue()(v), key(x)) ? left(x):right(x);
    }
    //x为新插入节点,Y为插入的父节点,v为插入的新值
    return __insert(x, y, v);
}


template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>
//注意这一行,返回值是pair类型,pair称为对组,这样写则返回值不返回一个值,而是返回两个值,这里可以看出返回的
//第一个值是iterator类型,即返回插入点的位置。返回的第二个值是bool类型,通过true或者false来判断插入是否成功

pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const value_type& v)
{
    link_type y = header;
    link_type x = root();
    bool comp = true;
    //从根节点开始查找适当的插入点
    while(x != 0){
        y = x;
        comp = key_compare(KeyOfValue()(v), key(y));
        //当插入的元素v<找到的插入点即y,则v往y的左边插入,否则右边
        x = comp ? left(x) : right(x);
    }
    //这里大家要注意理解,画图可以最直观的分析,这里自己也是看了好久才弄明白
    //下面的代码的作用是防止插入值重复。
    //分两种情况
    //(1)如果插入点的父节点是树的最左边节点,那么直接插入
    //(2)如果插入点的父节点不是树的最左边的节点,这个时候要考虑到插入的新节点
    //     是否可能跟已经插入的节点值重复,因此要进行回朔

    iterator j = iterator(y);
    //if(com)为真,也就是说当v<y,往左节点插入新值
    if(comp){
        if(j === begin()){
            return pair<iterator, bool>(__insert(x, y, v), true);
        }else{
            --j;
        }   
    }
    //满足这个条件即表示新插入的键值不与已经插入的节点的键值相等
    if(key_compare(key(j.node), KeyOfValue()(v))){
        return pair<iterator, bool>(__insert(x, y, v), true);
    }
    //键值重复不进行插入操作
    return pair<iterator, bool>(__insert(j, false);
}

template<class Key, class Value, class KeyOfValue, class Compare, class Alloc>
typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__insert(base_ptr x_, base_type y_,  const value_type& v)
{
    link_type x = (link_type)x_;
    link_type y = (link_type)y_;
    link_type z;
    //当key_compare(KeyOfValue()(v), keyy(y))为真时,也就是说v<y,往y的左节点插入,分3种情况
    //(1)y==header,插入的节点是root,这样就要注意要让root()=插入的节点,并且让header的左指针指向插入节点
    //即leftmost()=z
    //(2)y==leftmost,插入的地方是树的最左边的节点,注意的是要让header的左指针指向这个插入节点即leftmost()=z
    //(3)插入的仅仅是个普通的节点,直接让父节点y的左指针指向这个插入的节点即可

    if(y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))){
        z = create_node(v);
        //让leftmost() = z
        left(y) = z;
        //如果插入的节点是root节点,则让root作为header的左子节点
        if(y == header){
            root() = z;
            rightmost = z;
        //如果插入的地方是树的最左边的节点
        }else if(y == leftmost()){
            leftmost() = z;
        }
    }
    //当key_compare(KeyOfValue()(v), key(y))为假时,也就是说v>y,(注意这里规定的默认的key_compare规则是小与)
    //往插入点的父节点y的右节点插入,分1种情况
    //这里不用判断插入点为root节点,因为规定root节点只能作为header的左子节点插入

    else{
        z = create_node(v);
        right(y) = z;
        if(y == rightmost()){
            rightmost() = z;
        }
    }
    //设置新插入节点的父节点和左右节点
    parent(z) = y;
    left(z) = 0;
    right(z) = 0;
    //插入节点后记得要重新调整平衡和颜色
    __rb_tree_rebalance(z, header->parent);
    ++node_count;
    return iteratro(z);
}
//红黑树的旋转以及颜色的调整比较麻烦,所以大家要静下心来
//一:当插入点的父节点为祖父节点的左子树:
//    (1)如果伯父节点存在且为红
//    (2)如果伯父节点不存在或者为黑,
//         (1)则又要判断插入节点为父节点的左子树
//         (2)插入节点为父节点的右子树
//二:当插入点的父节点为祖父节点的右子树
//    (1)如果伯父节点存在且为红
//    (2)如果伯父节点不存在或者为黑
//         (1)插入点为父节点的左子树
//         (2)插入点为父节点的右子树

inline void __rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
    //新插入的节点必须为红节点,因为如果插入的新节点为黑节点,这样就打破了红黑树的约束条件
    //红黑树要求任一节点到NULL的任何的路径,所含之黑节点数目必须相等

    x->color = rb_tree_red;
    while(x != root && x->parent->color == rb_tree_red){
        //插入的父节点为祖父节点的左子树
        if(x->parent == x->parent->parent->left){
            //伯父节点存在且为红
            __rb_tree_node_base* y = x->parent->parent->right;
            if(y && y->color == __rb_tree_red){
                x->parent->color = __rb_tree_black;
                y->color = __rb_tree_black;
                x->parent->parent = __rb_tree_red;
                x = x->parent->parent;
            }
            //伯父节点不存在或者为黑
            else{
                if(x == x->parent->right){
                    x = x->parent;
                    __rb_tree_rotate_left(x, root);
                }
                x->parent->color = __rb_tree_black;
                x->parent->parent->color = __rb_tree_red;
                __rb_tree_rotate_right(x->parent->parent, root);
            }
        }
        //插入的节点的父节点为祖父节点的右子树
        else{
            //伯父节点存在且为红
            __rb_tree_node_base* y =x->parent->parent->left;
            if(y && y->color == __rb_tree_red){
                x->parent->color = __rb_tree_black;
                y->color = __rb_tree_black;
                x->parent->parent->color = __rb_tree_red;
                x = x->parent->parent;
            }
            //伯父节点不存在或者为黑
            else{
                if(x == x->parent->left){
                    x = x->parent;
                    __rb_tree_rotate_right(x, root);
                }
                x->parent->color = __rb_tree_black;
                x->parent->parent->color = __rb_tree_red;
                __rb_tree_rotate_left(x->parent->parent, root);
            }
        }
    }
    //根节点永远为黑
    root->color = __rb_tree_black;
}
//下面两个函数是红黑树节点的旋转
//x为旋转对象
//红黑树的旋转根AVL树的旋转一样,只是由于红黑树的节点又parent这个指针,所以旋转的时后要特别的注意这个指针的连接
//左旋:
//(1)将旋转目标x的右子节点Y的左子树挂在x的右子树上,
//(2)将y树挂在x的父节点上,
//(3)将y的左指针指向x;

//
inline void __rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
    __rb_tree_node_base* y = x->right;
    x->right = y->left;
    if(y->left != 0){
        y->left->parent = x;
    }
    y->parent = x->parent;
    if(x == root){
        root = y;
    }
    else if(x == x->parent->left){
        x->parent->left = y;
    }
    else{
        x->parent->right = y;
    }
    y->left = x;
    x->parent = y;
}
//右旋:
//(1)将旋转目标x的左子树y的右子树挂在x的左链上
//(2)将y树挂在x的父节点上
//(3)将x树挂在y的右链上

inline void __rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
    __rb_tree_node_base* y = x->right;
    x->left = y->right;
    if(y->right != 0){
        y->right->parent = x;
    }
    y->parent = x->parent;
    if(x == root){
        root = y;
    }
    else if(x == x->parent->left){
        x->parent->left = y;
    }else{
        x->parent->right = y;
    }
    y->right = x;
    x->parent = y;
    
}

};
#endif

 /

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值