STL之RB红黑树(二)

RB-tree的节点设计
RB-tree有红黑二色,并且拥有左右子节点,我们很容易就可以勾勒出其结构风貌。以下是SGI STL的实现代码。为了有更大的弹性,节点分为两层:从以下的minimum()和maximum()函数可清楚看出,RB-tree作为一个二叉搜索树,其极致是多么容易找到。由于RB-tree的各种操作时常需要上溯其父节点,所以特别在数据结构中安排了一个parent指针。

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;//RB树的许多操作,必须知道父节点
       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的节点图标,其中将 _rb_tree_node:value_field填为10:
在这里插入图片描述
RB-tree的迭代器
要成功将RB-tree实现一个泛型容器,迭代器的设计是一个关键。首先我们要考虑它的类别(category),然后要考虑它的前进(increment)、后退(decrement)、提领(dereference)、成员访问(member access)等操作。
为了更大的弹性,SGI将RB-tree迭代器实现为两层,这种设计理念和slist类似。下图所示便是双层节点和双层迭代器结构之间的关系。其中主要意义是:_rb_tree_node继承自 _rb_tree_node_base, _rb_tree_iterator继承自 _rb_tree_base_itertor。有啦这样的认知,我们就可以将迭代器稍作转型,然后解开RB-tree的所有奥秘,追踪其一切状态:
在这里插入图片描述
RB-tree迭代器属于双向迭代器,但不具备随机定位能力,其提领操作和成员访问操作与list十分相似,较为特殊的是其前进和后退操作。注意。RB-tree迭代器的前进操作operator++()调用了基层迭代器的increment(),RB-tree迭代器的后退操作operator–()则调用了基层迭代器的decrement()、前进或者后退的举止行为完全依据二叉搜索树的节点排列法则,再加上实现上的某些特殊技巧。

struct _rb_tree_base_iterator
{
      typedef _rb_tree_node_base::base_ptr base_ptr;
      tyopedf bidirectional_iterator_tag iterator_category;
      typedef ptrdiff_t difference_type;
      base_ptr node;//用来与容器之间产生一个连结关系(make a reference)

       void increment()
       {
             if(node->right!=0)
             {//如果有右节点,状况(1)
                   node=node->right;//就往右走
                   while(node->left!=0)//然后一直往左子树走到底
                     node=node->left;//即为解答
             }
             else{//没有右节点 状况(2)
                    base_ptr y=node->parent;//找出父节点
                    while(node==y->right)//如果现行节点本身是个右节点
                      node=y;//就一直上溯,直到“不为右子节点”为止
                      y=y->parent;
             }
             if (node->right!=y)//若此时的右子节点不等于此时的父节点
               node=y;//状况(3)此时的父节点即为解答
               //否则此时的node为解答
       }
       //以上判断“若此时的右子节点不等于此时的父节点”,是为了应付一种特殊情况:我们欲寻找根节点的下一节点,而恰好根节点无右子节点。当然,以上特护做法必须配合RB-tree根节点与特殊之header之间的特殊关系。
       void decrement()
       {
             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)
                    u=y->right;
                    node=y;
             }
             else {
               base_ptr y=node->left;
               while(node==y->left)
                node=y;
                y=y->parent;
             }
             node=y;
       }
};
//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;}
      #ifdef _SGI_STL_NO_ARROW_OPERATOR
      pointer operator->()const{return &(operator*());}
      #denif
      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;
      }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值