红黑树(RB-Tree)

红黑树性质:

 1、每个节点不是黑色就是红色

 2、根节点为黑色

3、节点为红色,其子节点必须为黑色(新增节点之父必须为黑)

4 、任一节点至NULL(树尾端)的任何路径,所含的黑节点必须相同。(新增节点必须为红)

RB-Tree的设计也采用了两层架构,以下是节点设计:

typedef bool __rb_tree_color_type;  
const __rb_tree_color_type __rb_tree_red = false;     // 红色为0  
const __rb_tree_color_type __rb_tree_black = true; // 黑色为1  
  
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)  
  {  
     while (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;   //节点的值  
};  

迭代器设计:

RB-Tree的迭代器属于双向迭代器,其中迭代器的前进及后退操作是调用了基层迭代器increment(),decrement(),如下是基层迭代器:

//迭代器基类,类型为bidirectional_iterator_tag,可以双向移动  
struct __rb_tree_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;  
  
  //下面只是为了实现oprerator++的,其他地方不会调用了。  
  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;  
      }  
      /* 
        若此时的右子节点不等于此时的父节点,此时的父节点即为解答,否则此时的node为解答. 
        这样做是为了应付一种特殊情况:我们欲寻找根节点的下一个节点。而恰巧根节点无右孩子。 
        当然,以上特殊做法必须配合RB-tree根节点与特殊header之间的特殊关系,在上面有图 
      */  
      if (node->right != y)      // 若此时的右子节点不等于此时的父节点  
        node = y;               // 此时的父节点即为解答  
                                // 否则此时的node为解答  
    }                         
    
  }  
  
   //查找前驱结点。  
  void decrement()  
  {  
    if (node->color == __rb_tree_red &&  // 如果是红节点,且  
        node->parent->parent == node)     // 父节点的父节点等于自己  
      node = node->right;                // 状况(1) 右子节点即为解答。  
      /* 
      以上情况发生于node为header时(亦即node为end()时)。注意,header之右孩子即 
      mostright,指向整棵树的max节点。上面有图 
      */  
    //左子树的最大值结点  
    else if (node->left != 0) {    
      base_ptr y = node->left;  
      while (y->right != 0)    
        y = y->right;      
      node = y;       
    }  
    /* 
    既非根节点,且无左子树。找其最低祖先节点y,且y的右孩子也是其祖先节点 
    */  
    else {                            
      base_ptr y = node->parent;         //找出父节点  
      while (node == y->left) {    
        node = y;                     
        y = y->parent;     
      }  
      node = y;  
    }  
  }  
};  

本来只有root节点,但处理时不方便,每到边界处还得再处理,所以为根节点增加一个父节点header,使header和root互为对方的父节点。

下面是RB-Tree的正规迭代器

template <class 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) { node = it.node; }  
  
  //重载操作符  
  reference operator*() const { return link_type(node)->value_field; }  
#ifndef __SGI_STL_NO_ARROW_OPERATOR  
  pointer operator->() const { return &(operator*()); }  
#endif /* __SGI_STL_NO_ARROW_OPERATOR */  
  
    //调用了increment()  
  self& operator++() { increment(); return *this; }  
  self operator++(int) {  
    self tmp = *this;  
    increment();  
    return tmp;  
  }  
    //调用了decrement  
  self& operator--() { decrement(); return *this; }  
  self operator--(int) {  
    self tmp = *this;  
    decrement();  
    return tmp;  
  }  
};  

RB-Tree的insert_unique()和insert_equal()是两种主要的插入操作

// 安插新值;允许键值重复。返回新插入节点的迭代器  
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(KeyOfValue()(v), key(x)) ? left(x) : right(x);  
  }  
  return __insert(x, y, v);  
}  
  
/* 
不允许键值重复,否则安插无效。 
返回值是个pair,第一个元素是个RB-tree迭代器,指向新增节点。 
第二个元素表示安插是否成功。 
*/  
template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>  
pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator, bool>  
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const Value& v)  
{  
  link_type y = header;  
  link_type x = root();  //从根节点开始  
  bool comp = true;  
  while (x != 0) {      // 从根节点开始向下寻找适当安插位置  
    y = x;  
    comp = key_compare(KeyOfValue()(v), key(x)); // v 键值小于目前节点的键值?  
    x = comp ? left(x) : right(x);  // 遇「大」往左,遇「小于或等于」往右  
  }  
  //离开while循环之后,y所指即为安插点的父节点,x必为叶子节点  
  
  iterator j = iterator(y);   // 令迭代器j指向安插点之父节点 y  
  if (comp) //如果离开while循环时comp为真,表示 父节点键值>v ,将安插在左孩子处  
    if (j == begin())   // 如果j是最左节点  
      return pair<iterator,bool>(__insert(x, y, v), true);  
      // 以上,x 为安插点,y 为安插点之父节点,v 为新值。  
    else    // 否则(安插点之父节点不是最左节点)  
      --j;  // 调整 j,回头准备测试...  
  if (key_compare(key(j.node), KeyOfValue()(v)))      
    // 小于新值(表示遇「小」,将安插于右侧)  
    return pair<iterator,bool>(__insert(x, y, v), true);  
  
  //若运行到这里,表示键值有重复,不应该插入  
  return pair<iterator,bool>(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_ptr y_, const Value& v) {  
//参数x_为新值安插点,参数y_为安插点之父节点,参数v 为新值  
  link_type x = (link_type) x_;  
  link_type y = (link_type) y_;  
  link_type z;  
  
  //key_compare是键值得比较准则,是个函数或函数指针  
  if (y == header || x != 0 || key_compare(KeyOfValue()(v), key(y))) {  
    z = create_node(v);  // 产生一个新节点  
    left(y) = z;          // 这使得当y为header时,leftmost()=z  
    if (y == header) {  
      root() = z;  
      rightmost() = z;  
    }  
    else if (y == leftmost())   // 如果y为最左节点  
      leftmost() = z;               // 维护leftmost(),使它永远指向最左节点  
  }  
  else {  
    z = create_node(v);  
    right(y) = z;               // 令新节点成为安插点之父节点y的右孩子  
    if (y == rightmost())  
      rightmost() = z;              // 维护rightmost(),使它永远指向最右节点  
  }  
  parent(z) = y;        // 设定新节点的父节点  
  left(z) = 0;      // 设定新孩子节点的左孩子  
  right(z) = 0;         // 设定新孩子节点的右孩子  
                          // 新节点的颜色将在 __rb_tree_rebalance() 设定并调整  
  __rb_tree_rebalance(z, header->parent);    // 参数一为新增节点,参数二为root  
  ++node_count;     // 节点数增加  
  return iterator(z);   // 返回迭代器,指向新增节点  
}  

作为平衡树,最重要的是调节保持平衡,如下几个函数:

//左旋转  
inline void   
__rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)  
{  
  // x 为旋转点  
  __rb_tree_node_base* y = x->right; // y为x的右孩子  
  x->right = y->left;  
  if (y->left !=0)  
    y->left->parent = x;      // 不要忘了回马枪设置父节点  
  y->parent = x->parent;  
  
  // 令 y 完全顶替 x 的地位(必须将x对其父节点的关系完全接收过来)  
  if (x == root)                    // x 为根节点  
    root = y;  
  else if (x == x->parent->left)  // x 为父节点的左孩子  
    x->parent->left = y;  
  else                          // x 为父节点的右孩子  
    x->parent->right = y;           
  y->left = x;  
  x->parent = y;  
}  
  
//右旋转  
inline void   
__rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root)  
{  
  // x 为旋转点  
  __rb_tree_node_base* y = x->left;  // y x的左孩子  
  x->left = y->right;  
  if (y->right != 0)  
    y->right->parent = x;     // 別忘了回马枪设置父节点  
  y->parent = x->parent;  
  
  // 令 y 完全顶替 x 的地位(必须将x对其父节点的关系完全接收过来)  
  if (x == root)                    // x 为根节点  
    root = y;  
  else if (x == x->parent->right) // x 为父节点的右孩子  
    x->parent->right = y;  
  else                          // x 为父节点的左孩子  
    x->parent->left = y;  
  y->right = x;  
  x->parent = y;  
}  
  
  
//重新令RB-tree平衡(改变颜色和旋转)参数x为新增节点,参数二为root节点  
inline void   
__rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)  
{  
  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;   // 令y 为伯父节点  
      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 {    // 无伯父节点或伯父节点为黑色(NULL就是黑色)  
        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; // y为伯父节点  
      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 {    // 无伯父节点或伯父节点为黑色(NULL就是黑色)  
        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); // 第一个参数做旋转  
      }  
    }  
  } // while 結束  
  root->color = __rb_tree_black; // 根节点永远为黑色  
}  
//删除结点z  
inline __rb_tree_node_base*  
__rb_tree_rebalance_for_erase(__rb_tree_node_base* z,  
                              __rb_tree_node_base*& root,  
                              __rb_tree_node_base*& leftmost,  
                              __rb_tree_node_base*& rightmost)  
{  
  __rb_tree_node_base* y = z;  
  __rb_tree_node_base* x = 0;  
  __rb_tree_node_base* x_parent = 0;  
  if (y->left == 0)             // z has at most one non-null child. y == z.  
    x = y->right;               // x might be null.  
  else  
    if (y->right == 0)          // z has exactly one non-null child.  y == z.  
      x = y->left;              // x is not null.  
    else {                      // z has two non-null children.  Set y to  
      y = y->right;             //   z's successor.  x might be null.  
      while (y->left != 0)  
        y = y->left;  
      x = y->right;  
    }  
  if (y != z) {                 // relink y in place of z.  y is z's successor  
    z->left->parent = y;   
    y->left = z->left;  
    if (y != z->right) {  
      x_parent = y->parent;  
      if (x) x->parent = y->parent;  
      y->parent->left = x;      // y must be a left child  
      y->right = z->right;  
      z->right->parent = y;  
    }  
    else  
      x_parent = y;    
    if (root == z)  
      root = y;  
    else if (z->parent->left == z)  
      z->parent->left = y;  
    else   
      z->parent->right = y;  
    y->parent = z->parent;  
    __STD::swap(y->color, z->color);  
    y = z;  
    // y now points to node to be actually deleted  
  }  
  else {                        // y == z  
    x_parent = y->parent;  
    if (x) x->parent = y->parent;     
    if (root == z)  
      root = x;  
    else   
      if (z->parent->left == z)  
        z->parent->left = x;  
      else  
        z->parent->right = x;  
    if (leftmost == z)   
      if (z->right == 0)        // z->left must be null also  
        leftmost = z->parent;  
    // makes leftmost == header if z == root  
      else  
        leftmost = __rb_tree_node_base::minimum(x);  
    if (rightmost == z)    
      if (z->left == 0)         // z->right must be null also  
        rightmost = z->parent;    
    // makes rightmost == header if z == root  
      else                      // x == z->left  
        rightmost = __rb_tree_node_base::maximum(x);  
  }  
  if (y->color != __rb_tree_red) {   
    while (x != root && (x == 0 || x->color == __rb_tree_black))  
      if (x == x_parent->left) {  
        __rb_tree_node_base* w = x_parent->right;  
        if (w->color == __rb_tree_red) {  
          w->color = __rb_tree_black;  
          x_parent->color = __rb_tree_red;  
          __rb_tree_rotate_left(x_parent, root);  
          w = x_parent->right;  
        }  
        if ((w->left == 0 || w->left->color == __rb_tree_black) &&  
            (w->right == 0 || w->right->color == __rb_tree_black)) {  
          w->color = __rb_tree_red;  
          x = x_parent;  
          x_parent = x_parent->parent;  
        } else {  
          if (w->right == 0 || w->right->color == __rb_tree_black) {  
            if (w->left) w->left->color = __rb_tree_black;  
            w->color = __rb_tree_red;  
            __rb_tree_rotate_right(w, root);  
            w = x_parent->right;  
          }  
          w->color = x_parent->color;  
          x_parent->color = __rb_tree_black;  
          if (w->right) w->right->color = __rb_tree_black;  
          __rb_tree_rotate_left(x_parent, root);  
          break;  
        }  
      } else {                  // same as above, with right <-> left.  
        __rb_tree_node_base* w = x_parent->left;  
        if (w->color == __rb_tree_red) {  
          w->color = __rb_tree_black;  
          x_parent->color = __rb_tree_red;  
          __rb_tree_rotate_right(x_parent, root);  
          w = x_parent->left;  
        }  
        if ((w->right == 0 || w->right->color == __rb_tree_black) &&  
            (w->left == 0 || w->left->color == __rb_tree_black)) {  
          w->color = __rb_tree_red;  
          x = x_parent;  
          x_parent = x_parent->parent;  
        } else {  
          if (w->left == 0 || w->left->color == __rb_tree_black) {  
            if (w->right) w->right->color = __rb_tree_black;  
            w->color = __rb_tree_red;  
            __rb_tree_rotate_left(w, root);  
            w = x_parent->left;  
          }  
          w->color = x_parent->color;  
          x_parent->color = __rb_tree_black;  
          if (w->left) w->left->color = __rb_tree_black;  
          __rb_tree_rotate_right(x_parent, root);  
          break;  
        }  
      }  
    if (x) x->color = __rb_tree_black;  
  }  
  return y;  
}  

 

posted on 2016-03-22 10:41  RenewDo  阅读(457)  评论(0编辑  收藏  举报

导航