红黑二叉搜索树(RB-Tree)

一、介绍

上一篇介绍了AVL-Tree,这里介绍另一个被广泛运用的平衡二叉搜索树(红黑树)(提示:知识是递进的,如果二叉搜索树都不了解,请学习相关内容再来)。

所谓的RB-Tree,不仅是一个二叉搜索树,还要满足以下条件:

(1)每个节点不是黑色就是红色。

(2)根节点是黑色。

(3)如果一个节点是红色的,则它的子节点必须是黑色的,也就是说不可能出现两个连续的红色节点,不过两个连续的黑色节点是可能出现的。

(4)从任意一个节点到NULL(树尾端)的任何路径,所包含的黑节点数必须相同。

根据规则4,新增节点必须为红;根据规则3,新增节点之父节点必须为黑。当心节点根据二叉搜索树的规则到达其插入点,却未能符合上述条件时,就必须调整颜色并旋转树形。如下图所示,(注意:深色表示黑,浅色表示红)

二、插入

要点:

1、红黑树在插入数据的时候,会先遍历数据应该插入到哪个位置,插入的位置肯定在底部,不可能在中间突然插入一个值。

2、插入的数据一定是红色的(因为要遵守红黑树的第4条规则,如果有一条分支增加了一个黑色节点,就会打破该规则)

3、插入之后,为了满足规则4,就需要用到换色与左旋、右旋的操作了

现在我们延续上图的状态,插入一些节点,看看会产生什么

假设我们对上图,插入3,8,35,75。根据二叉搜索树的规则,它们应该如下图所示。这样就破坏了红黑的规则,我们必须调整树形,也就是旋转树形并改变节点的颜色。

为了方便讨论,让我先为某些特殊节点定义一些代名.以下讨论都将沿用这些
代名.假设新节点为X,其父节点为P(Parent),祖父节点为G(Grand),伯父节点(父节点之兄弟节点)为S(Sibling),曾祖父节点为GG。现在,根据二叉搜索树的规则,新节点X必为叶子节点。根据红黑树规则4,X必为红。若P亦为红(这就违反了规则3,必须调整树形),则G必为黑(因为原为RB-tree,必须遵循规则3)。于是,根据Ⅹ的插入位置及外围节点(S和GG)的颜色,有了以下四种考虑 :

注意,此时可能产生不平衡状态(高度相差1以上)例如图中的A和B为null,D或E不为null。这倒没关系,因为RB-tree的平衡性本来就比AVL-tree弱,然而RB-tree通常能够导致良好的平衡状态。是的,经验告诉我们,RB-tree的搜寻平均效率和AVL-tree几乎相等 

最后一个步骤

为了避免状况4——父子节点皆为红色”的情况。持续向RB-tree的上层结构发展,形成处理时效上的瓶颈,我们可以施行一个由上而下的步骤( top-downprocedure):假设新增节点为A,那么就延着A的路径,只要看到有某节点X的两个子节点皆为红色,就把X改为红色,并把两个子节点改为黑色,如图5-15e所示 

 三、代码实现

        #ifndef CM_RBTREE_HPP
        #define CM_RBTREE_HPP  
      	#include "BinarySearchTree.hpp"
      	namespace cm
      	{
      	  template<typename T> class RBTreeNode;
      	  template<typename T> class RBTreeIterator;
      	  template<typename T> class RBTree;
      	
      	  template<typename T>
      	    class RBTreeNode
      	    {
      	      public:
      	        typedef T VALUE_TYPE;
      	        enum Color_t { 
      	          COLOR_BLACK,
      	          COLOR_RED
      	        };
      	
      	      public:
      	        explicit RBTreeNode(const T& v=T(), Color_t c=COLOR_BLACK)
      	          : value_(v)
      	            , left_(NIL)
      	            , right_(NIL)
      	            , parent_(NIL)
      	            , color_(c)
      	      {
      	      }
      	
      	        RBTreeNode<T>* left()  {  return left_;   }
      	        RBTreeNode<T>* right() {  return right_;  }
      	        RBTreeNode<T>* parent(){  return parent_; }
      	        RBTreeNode<T>* left()   const {  return left_;   }
      	        RBTreeNode<T>* right()  const {  return right_;  }
      	        RBTreeNode<T>* parent() const {  return parent_; }
      	        const T&     value()        const {  return value_;  }
      	        Color_t color()             const {  return color_;  }
      	
      	        void left(RBTreeNode<T>* node)  {  left_ = node;   }
      	        void right(RBTreeNode<T>* node) {  right_ = node;  }
      	        void parent(RBTreeNode<T>* node){  parent_ = node; }
      	        void value(const T& value)          {  value_ = value; }
      	        void color(Color_t c)               { color_ = c;      }
      	
      	        operator bool() const
      	        {
      	          return this != NIL;
      	        }
      	
      	        bool operator !() const
      	        {
      	          return this == NIL;
      	        }
      	
      	      public:
      	        static RBTreeNode<T>* NIL;
      	
      	      private:
      	        T            value_;
      	        RBTreeNode<T>* left_;
      	        RBTreeNode<T>* right_;
      	        RBTreeNode<T>* parent_;
      	        Color_t color_;
      	    }; 
      	  template<typename T>
      	    RBTreeNode<T>* RBTreeNode<T>::NIL(new RBTreeNode<T>());
      	
      	  template<typename T>
      	    class RBTree: public BinarySearchTree_T< RBTreeNode<T> >
      	  {
      	    public:
      	      typedef RBTreeNode<T> Node;
      	
      	    public:
      	      size_t bh() const
      	      {
      	        return this->bh(this->getRoot());
      	      }
      	      size_t bh(const Node* node) const
      	      {
      	        Node* n = node;
      	        size_t h =  ;
      	        while (n) {
      	          if (n->color() == Node::COLOR_BLACK) {
      	            ++h;
      	          }
      	          n = n->left();
      	        }
      	        return h;
      	      }
      	      size_t insert(const T& key)
      	      {
      	        Node* z = new Node(key, Node::COLOR_RED);    // 要插入的节点
      	        Node* y = Node::NIL;    // y 是 x 的父节点
      	        Node* x = this->root();
      	        while (x != Node::NIL) {
      	          y = x;
      	          if (key == x->value()) {
      	            return  0;
      	          }
      	
      	          if (key < x->value()) {
      	            x = x->left();
      	          }
      	          else {
      	            x = x->right();
      	          }
      	        }
      	
      	        z->parent(y);
      	
      	        if (y == Node::NIL) {
      	          this->root_ = z;
      	          this->root_->parent(Node::NIL);
      	        }
      	        else {
      	          if(key < y->value()) {
      	            y->left(z);
      	          }
      	          else {
      	            y->right(z);
      	          }
      	        }
      	
      	        z->left(Node::NIL);
      	        z->right(Node::NIL);
       	          insert_fixup(z);
      	
      	        ++this->size_;
      	        return  ;
      	      }
      	
      	      void remove(Node* z)
      	      {
      	        Node* y = Node::NIL;
      	        Node* x = Node::NIL;
      	        if (z->left() == Node::NIL || z->right() == Node::NIL) {
      	          y = z;
      	        }
      	        else {
      	          //y = this->successor(z);
      	          y = z->right();
      	          while (y->left() != Node::NIL) {
      	            y = y->left();
      	          }
      	        }
      	
      	        // x 是 y的唯一孩子
      	        if (y->left() != Node::NIL) {
      	          x = y->left();
      	        }
      	        else {
      	          x = y->right();
      	        }
      	
      	        x->parent(y->parent());
      	
      	        if(y->parent() == Node::NIL) {
      	          this->root_ = x;
      	        }
      	        else {
      	          if (y == y->parent()->left()) {
      	            y->parent()->left(x);
      	          }
      	          else {
      	            y->parent()->right(x);
      	          }
      	        }
      	
      	        if (y != z) {
      	          z->value(y->value());
      	        }
      	
      	        if (y->color() == Node::COLOR_BLACK) {
      	          this->delete_fixup(x);
      	        }
      	
      	        delete y;
      	        --this->size_;
      	      }
      	
      	      /// 如果key存在,删除并返回 ,否则返回 
      	      size_t remove(const T& key)
      	      {
      	        Node* node = this->find(key);
      	        if (node != Node::NIL) {
      	          this->remove(node);
      	          return  ;
      	        }
      	
      	        return  ;
      	      }
      	
      	    private:
      	      void left_rotate(Node* x)
      	      {
      	        Node* y = x->right();
      	
      	        // 把y的左子数变成x的右子树
      	        x->right(y->left());
      	
      	        if (y->left() != Node::NIL) {
      	          y->left()->parent(x);
      	        }
      	
      	        if (y != Node::NIL) {
      	          y->parent(x->parent());
      	        }
      	
      	        if (x->parent() == Node::NIL) {
      	          this->root_ = y;
      	        }
      	        else {
      	          if (x == x->parent()->left()) {
      	            x->parent()->left(y);
      	          }
      	          else {
      	            x->parent()->right(y);
      	          }
      	        }
      	
      	        // 把x变成y的左子节点
      	        y->left(x);
      	        if (x != Node::NIL) {
      	          x->parent(y);
      	        }
      	      }
      	      void right_rotate(Node* x)
      	      {
      	        Node* y = x->left();
      	         x->left(y->right());
      	
      	        if (y->right() != Node::NIL) {
      	          y->right()->parent(x);
      	        }
      	
      	        if (y != Node::NIL) {
      	          y->parent(x->parent());
      	        }
      	
      	        if (x->parent() == Node::NIL) {
      	          this->root_ = y;
      	        }
      	        else {
      	          if (x == x->parent()->left()) {
      	            x->parent()->left(y);
      	          }
      	          else {
      	            x->parent()->right(y);
      	          }
      	        }
      	
      	        y->right(x);
      	        if (x != Node::NIL) {
      	          x->parent(y);
      	        }
      	      }
      	
      	      void insert_fixup(Node* z)
      	      {
      	        Node* y = Node::NIL;
      	        while (z != this->root() && z->parent()->color() == Node::COLOR_RED) {
      	          if (z->parent() == z->parent()->parent()->left()) {
      	            y = z->parent()->parent()->right();
      	            if (y->color() == Node::COLOR_RED) {
      	              z->parent()->color(Node::COLOR_BLACK);
      	              y->color(Node::COLOR_BLACK);
      	              z->parent()->parent()->color(Node::COLOR_RED);
      	              z = z->parent()->parent();
      	            }
      	            else {
      	              if (z == z->parent()->right()) {
      	                z = z->parent();
      	                this->left_rotate(z);
      	              }
      	
      	              z->parent()->color(Node::COLOR_BLACK);
      	              z->parent()->parent()->color(Node::COLOR_RED);
      	              this->right_rotate(z->parent()->parent());
      	            }
      	          }
      	          else {
      	            y = z->parent()->parent()->left();
      	            if (y->color() == Node::COLOR_RED) {
      	              z->parent()->color(Node::COLOR_BLACK);
      	              y->color(Node::COLOR_BLACK);
      	              z->parent()->parent()->color(Node::COLOR_RED);
      	              z = z->parent()->parent();
      	            }
      	            else {
      	              if (z == z->parent()->left()) {
      	                z = z->parent();
      	                this->right_rotate(z);
      	              }
      	
      	              z->parent()->color(Node::COLOR_BLACK);
      	              z->parent()->parent()->color(Node::COLOR_RED);
      	              this->left_rotate(z->parent()->parent());
      	            }
      	          }
      	        }
      	
      	        this->root()->color(Node::COLOR_BLACK);
      	      }
      	
      	      void delete_fixup(Node* x)
      	      {
      	        Node* w = Node::NIL;
      	        while (x != this->root() && x->color() == Node::COLOR_BLACK) {
      	          if (x == x->parent()->left()) {
      	            w = x->parent()->right();
      	            if (w->color() == Node::COLOR_RED) {
      	              w->color(Node::COLOR_BLACK);
      	              x->parent()->color(Node::COLOR_RED);
      	              this->left_rotate(x->parent());
      	              w = x->parent()->right();
      	            }
      	            if (w->left()->color() == Node::COLOR_BLACK && w->right()->color() == Node::COLOR_BLACK) {
      	              w->color(Node::COLOR_RED);
      	              x = x->parent();
      	            } else {
      	              if (w->right()->color() == Node::COLOR_BLACK) {
      	                w->left()->color(Node::COLOR_BLACK);
      	                w->color(Node::COLOR_RED);
      	                right_rotate(w);
      	                w = x->parent()->right();
      	              }
      	              w->color(x->parent()->color());
      	              x->parent()->color(Node::COLOR_BLACK);
      	              w->right()->color(Node::COLOR_BLACK);
      	              left_rotate(x->parent());
      	              x = this->root();
      	            }
      	          } else {
      	            w = x->parent()->left();
      	            if (w->color() == Node::COLOR_RED) {
      	              w->color(Node::COLOR_BLACK);
      	              x->parent()->color(Node::COLOR_RED);
      	              right_rotate(x->parent());
      	              w = x->parent()->left();
      	            }
      	            if (w->right()->color() == Node::COLOR_BLACK && w->left()->color() == Node::COLOR_BLACK) {
      	              w->color(Node::COLOR_RED);
      	              x = x->parent();
      	            } else {
      	              if (w->left()->color() == Node::COLOR_BLACK) {
      	                w->right()->color(Node::COLOR_BLACK);
      	                w->color(Node::COLOR_RED);
      	                left_rotate(w);
      	                w = x->parent()->left();
      	              }
      	              w->color(x->parent()->color());
      	              x->parent()->color(Node::COLOR_BLACK);
      	              w->left()->color(Node::COLOR_BLACK);
      	              right_rotate(x->parent());
      	              x = this->root();
      	            }
      	          }
      	        }
      	
      	        x->color(Node::COLOR_BLACK);
      	      }
      	  };
      	
      	  template<typename T>
      	    class RBTreeIterator
      	    {
      	      public:
      	        RBTreeIterator()
      	          : tree_(RBTreeNode<T>::NIL), current_(RBTreeNode<T>::NIL)
      	        {
      	        }
      	
      	        RBTreeIterator(RBTree<T>& tree, typename RBTree<T>::Node* current)
      	          : tree_(tree), current_(current)
      	        {
      	        }
      	
      	        const T& operator*() const
      	        {
      	          return current_->value();
      	        }
      	
      	        T* operator->()
      	        {
      	          return current_;
      	        }
      	
      	        bool operator==(const RBTreeIterator& rhs) const
      	        {
      	          return current_ == rhs.current_;
      	        }
      	
      	        bool operator!=(const RBTreeIterator& rhs) const
      	        {
      	          return current_ != rhs.current_;
      	        }
      	        RBTreeIterator& operator++()
      	        {
      	          current_ = tree_.successor(current_);
      	          return *this;
      	        }
      	
      	      private:
      	        RBTree<T>& tree_;
      	        typename RBTree<T>::Node* current_;
      	    };
      	
      	
      	} // end namespace cm
      	
      	#endif // CM_RBTREE_HPP

 参考:

【算法】红黑树插入数据(变色,左旋、右旋)(二)_lsr40的博客-CSDN博客_红黑树左旋右旋

深入理解红黑树及C++实现 - 守功 - 博客园

红黑树的C++实现与解析_wang11chao01的博客-CSDN博客_c++红黑树案例

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值