STL红黑树

红黑树

概念

红黑树是基于2-3树的思想的一种实现:红黑树是并不是严格的AVL树而是基于普通的二叉树在其中引入了红黑结点的概念,红结点与父节点共同对应2-3树中的3-结点,1个黑结点对应2-3树中的2-结点(普通节点)所以他外观上并不是平衡的,而实际上是黑色平衡的

性质

1.每一个结点不是黑结点就是红节点
2.如果一个结点时红节点则它的两个子节点是黑结点(1个红节点和它连接的父结点构成1个3-结点,两个就是4-结点)
3.红黑树是黑色平衡,任意空连接到根结点的路径上的黑结点数目相等
4.根结点为黑色
推论:从根到叶子的最长的可能路径不多于最短的可能路径的两倍长,因为最长路径就是红黑交替,最短是全是黑结点所以不可能多于2倍

实现

结点类

STL红黑树中我们将连接的颜色表现在结点中在节点类中添加color成员,red代表他与父节点相连的连接为红链接,black为黑链接。
由于 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;		//指向右节点
};

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

迭代器

因为是双层结点所以迭代器也是双层的:__rb_tree_iterator 继承自 __rb_tree_base_iterator。
红黑树的迭代器是一种双向迭代器,既可以访问下一个元素也可以访问上一个元素:基类迭代器中包含两个方法increment()和decrement(),真正的迭代器根据这两个方法重载++,–,*,&四个运算符
基类迭代器
因为红黑树构造之后整体元素是有序的所以访问上一个元素就是访问最后一个比它小的元素,访问下一个元素就是访问第一个比它大的元素。

//迭代器:因为结点是双层,所以迭代器也采用双层具体:rb_tree_node 继承自 rb_tree_node_base,rb_tree_iterator 继承自 rb_tree_base_iterator
//rb_tree的迭代器是双向迭代器但不能随机移动
//基层迭代器
struct __rb_tree_node_base_iterator
{
    typedef __rb_tree_node_base::base_ptr base_ptr;
    typedef bidirectional_iterator_tag iterator_categorty //双向迭代器
    typedef ptrdiff_t difference_type;

    base_ptr node; //用来和容器产生连接关系

    //寻找该元素的下一个元素(第一个比他大的元素)
    void increment(){
        //如果有右子结点,则下一个元素就是右子树的最左结点
        if(node->right != nullptr){
            node = node->right;
            while(node->left != nullptr)
                node = node->left;
        }
        //没有右子结点,说明是红黑树中某一棵子树的最右结点,循环找该节点的父节点,直到找到这颗子树的根结点的父节点,
        //根结点的父节点的右子节点就是下一个元素
        else{
            base_ptr y = node->parent;
            //循环找该节点的父节点,直到此时的node不是y的右子结点,
            //如果node不是y的右子节点,此时已经找到了这颗子树的根结点的父节点,且node所在的子树是左子树,
            //此时子树根结点的父节点就是下一个元素
            while(node == y->right){
                node = y;
                y = y->parent;
            }
            //如果此时node的右子节点不是y即右子结点不是本身,即node不是根节点的父节点header
            //此时node的父节点y就是下一个结点
            if(node->right != y){
                node = y;
            }
            //如果是此时node为header则下一个元素就是node本身
            //这是一种特殊情况:我们欲寻找根节点的下一节点,而恰巧根节点无右子节点
        }
    }
    //寻找该元素的上一个元素,(最后一个比他小的元素
    void decrement(){
        //如果此时的结点是header:结点为红节点,父节点的父节点等于自己
        // 这种情况发生在node为header时,即node为end()时
        // 注意:header的右子节点为mostright,指向整棵树的max节点
        if(node->color == red && node->parent->parent == node){
            node = node->right;
        }
        //如果有左子结点,则上一个元素就是左子树的最右结点
        else if(node->left != nullptr){
            node = node->left;
            while(node->right != nullptr){
                node = node->right;
            }
        }
        //如果没有左子结点,则说明node是红黑树某一子树的最左结点,循环找该节点的父节点,直到找到这棵子树的根结点的父节点
        else{
            base_ptr y = node->parent;
            while(node == y->left){
                node = y;
                y = y->parent;
            }
            //如果node不是y的左子节点说明node所在的子树是右子树,
            //根结点的父节点就是上一个元素
            node = y;
        }
    }
};

真正的迭代器
继承基类方法重载运算符

//真正的迭代器
template <class Value, class Ref, class Ptr>
struct __rb_tree_node_iterator:rb_tree_node_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_node_iterator(){}
    __rb_tree_node_iterator(link_type x){node = x;}
    __rb_tree_node_iterator(const iterator& x){node = x.node;}
    //重载++,--,&,*操作符
    self& operator++(){
        increment();
        return *this;
    }
    self operator++(int){
        self tem = *this;
        increment();
        return tem;
    }
    self& operator--(){
        decrement();
        return *this;
    }
    self operator--(int){
        self tem = *this;
        decrement();
        return tem;
    }
    reference operator*(){
        return node->value_field;
    }
    pointer operator&(){
        return &(operator*());
    }
};

RB-tree

红黑树就是一个二叉树,但是在STL实现的时候增加了一个特殊的结点header,
header与root互为父节点,header的左子结点是红黑树中的最小值,右子节点是红黑树的最大值。这个结点的设置主要是为了方便对根结点的处理:根结点也有了自己的父亲而且他父亲的父亲还是它本身,这有利于在平衡化的时候统一操作
初始化的时候红黑树的根结点是黑色的,与之相区分header结点设为红色,左子节点指向本身,右子节点指向本身

数据结构设计
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;
protected:
  // RB-tree的数据结构
  size_type node_count; // 记录树的节点个数
  link_type header;         // 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; }
 
  // 以下六个函数用来取得节点的成员
  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); }
 
  // 以下六个函数用来取得节点的成员,由于双层设计,导致这里需要两个定义
  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:
    // RBTree的迭代器定义
  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(); }        // RBTree的起始节点为左边最小值节点
  const_iterator begin() const { return leftmost(); }
  iterator end() { return header; }                         // RBTree的终止节点为右边最大值节点
  const_iterator end() const { 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); }  // 获取红黑树的最大节点个数,
                                                                                                                // 没有容量的概念,故为sizetype最大值
};

构造函数

红黑树的默认构造函数构造了一颗空树,这颗空树中只有一个header结点
红黑树还支持拷贝构造函数
主要是调用配置器给结点分配空间

template <class Key, class Value, class KeyOfValue, class Compare,
          class Alloc = alloc>
class rb_tree {
    // 这部分代码是从红黑树的结构定义中提取出来的
protected:
    typedef simple_alloc<rb_tree_node, Alloc> rb_tree_node_allocator; // 专属配置器
 
  link_type get_node() { return rb_tree_node_allocator::allocate(); } // 配置空间
 
  link_type create_node(const value_type& x) {
    link_type tmp = get_node();            // 配置空間
    __STL_TRY {
      construct(&tmp->value_field, x);    // 构造内容
    }
    __STL_UNWIND(put_node(tmp));
    return tmp;
  }
  // 初始化函数,用来初始化一棵RBTree
  void init() {
    header = get_node();    // 产生一个节点空间,令header指向它
    color(header) = __rb_tree_red; // 令header为红色,用来区分header和root
    root() = 0;
    leftmost() = header;    // 令header的左子节点为其自己
    rightmost() = header;    // 令header的右子节点为其自己
  }
  // 真正的默认构造函数
  rb_tree(const Compare& comp = Compare())
  : node_count(0), key_compare(comp) { init(); }    // 直接调用初始化函数
 
  // 带参构造函数,以另一棵RBTree为初值来初始化
  rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) 
    : node_count(0), key_compare(x.key_compare)
  { 
    header = get_node();    // 產生一個節點空間,令 header 指向它
    color(header) = __rb_tree_red;    // 令 header 為紅色
    if (x.root() == 0) {    //  如果 x 是個空白樹
      root() = 0;
      leftmost() = header;     // 令 header 的左子節點為自己。
      rightmost() = header; // 令 header 的右子節點為自己。
    }
    else {    //  x 不是一個空白樹
      __STL_TRY {
        root() = __copy(x.root(), header);        //调用copy函数
      }
      __STL_UNWIND(put_node(header));
      leftmost() = minimum(root());    // 令 header 的左子節點為最小節點
      rightmost() = maximum(root());    // 令 header 的右子節點為最大節點
    }
    node_count = x.node_count;
  }
  // copy函数定义如下
  template <class K, class V, class KeyOfValue, class Compare, class Alloc>
    typename rb_tree<K, V, KeyOfValue, Compare, Alloc>::link_type 
    rb_tree<K, V, KeyOfValue, Compare, Alloc>::__copy(link_type x, link_type p) {
      link_type top = clone_node(x); // 克隆root节点
      top->parent = p;  // 将root节点父节点指向p
        // 以下为非递归的二叉树复制过程
      __STL_TRY {
        if (x->right)
          top->right = __copy(right(x), top); // 一直copy右子节点
        p = top;    
        x = left(x);    // 取左节点
 
        while (x != 0) {    // 左子节点不为空
          link_type y = clone_node(x);  // 克隆左子节点
          p->left = y;  // p的左子节点设为y
          y->parent = p;    // y的父节点设为p
          if (x->right)     // 如果左子节点还有右子节点,继续复制
            y->right = __copy(right(x), y);
          p = y;    // 直到没有左子节点
          x = left(x);
        }
      }
      __STL_UNWIND(__erase(top));
 
      return top;
    }
    // clone一个节点函数
  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;
    }
}
析构函数

调用配置器释放空间
先调用clear清除所有的结点,并将header变回初始状态(左子节点指向本身,右子节点指向本身),然后再释放header空间

template <class Key, class Value, class KeyOfValue, class Compare,
          class Alloc = alloc>
class rb_tree {
    // 这部分代码是从红黑树的结构定义中提取出来的
protected:
    void put_node(link_type p) { rb_tree_node_allocator::deallocate(p); }
    // 析构一个节点
    void destroy_node(link_type p) {
    destroy(&p->value_field);        // 析构内容
    put_node(p);                    // 释放空间 
  }
  // 析构函数
  ~rb_tree() {
    clear();
    put_node(header);
  }
  // 清除整棵树并初始化header节点
  void clear() {
    if (node_count != 0) {
      __erase(root());
      // 初始化Header节点
      leftmost() = header;
      root() = 0;
      rightmost() = header;
      node_count = 0;
    }
  }
  // 清除RBTree的每个节点
    template <class Key, class Value, class KeyOfValue, class Compare, class Alloc>
    void rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::__erase(link_type x) {
      // 直接清,不用调平衡
      while (x != 0) {
        __erase(right(x));
        link_type y = left(x);
        destroy_node(x);
        x = y;
      }
    }
}
插入

插入的过程和普通的二叉查找树一样,只不过插入之后需要进行平衡化调整
规定插入的结点都是红节点,模拟2-3树中插入的结点都是向父节点插组成3-结点或4-结点一样
插入的过程是先调用insert_unique(const Value &v)找到待插入v将要插入的位置,找到之后调用_insert(base_ptr x_ , base_ptr y_ , const Value &v)插入结点并再插入的过程中更新header结点,插入之后调用_rb_tree_rebalance(z , header->parent)调整平衡
insert_unique(const Value &v)
新建迭代器x,y,分别指向root和header,从root结点开始比较v的键和x的键,更新x,y的值使得找到位置时x为待插入位置空连接,y为x的父节点,

// 此插入函数不允许重复
// 返回的是一个pair,第一个元素为红黑树的迭代器,指向新增节点
// 第二个元素表示插入操作是否成功的
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)  
{  
    rb_tree_node* y = header;    // 根节点root的父节点  
    rb_tree_node* 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所指即插入点之父节点(此时的它必为叶节点)  
    iterator j = iterator(y);     // 令迭代器j指向插入点之父节点y  
    if(comp)     // 如果离开while循环时comp为真(表示遇“大”,将插入于左侧)  
    {  
        if(j == begin())    // 如果插入点之父节点为最左节点  
            return pair<iterator , bool>(_insert(x , y , v) , true);// 调用_insert函数
        else     // 否则(插入点之父节点不为最左节点)  
            --j;   // 调整j,回头准备测试  
    }  
    if(key_compare(key(j.node) , KeyOfValue()(v) ))  
        // 新键值不与既有节点之键值重复,于是以下执行安插操作  
        return pair<iterator , bool>(_insert(x , y , v) , true);  
    // 以上,x为新值插入点,y为插入点之父节点,v为新值  
 
    // 进行至此,表示新值一定与树中键值重复,那么就不应该插入新值  
    return pair<iterator , bool>(j , false);  
} 
 

insert(base_ptr x , base_ptr y_ , const Value &v)
在指定位置x上插入新节点,并调整header的内容,调用平衡化函数使红黑树平衡

// 真正地插入执行程序 _insert()  
// 返回新插入节点的迭代器
template<class Key , class Value , class KeyOfValue , class Compare , class Alloc>  
typename<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 是键值大小比较准则。应该会是个function object  
    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);  // 返回一个迭代器,指向新增节点  
}  
平衡化调整

因为插入之前的树是平衡的所以我们只需要关注插入结点,插入节点的父结点,插入结点的父结点的父节点即可
插入结点x为红节点
根据红黑树的性质只有当父节点为红节点时需要调整,(产生了临时4-结点)
根据结点x的父节点为左子结点还是右子结点分为两种镜像的操作
根据父节点的父节点的另一个字结点(叔叔结点)是红节点还是黑结点在上面的基础上继续细分为两种情况。
在这2大种情况之内各自只有1种情况需要旋转操作:叔叔结点不存在或为黑结点
而根据x结点为内侧插入还是外侧插入判断做2次旋转还是1次旋转
第一次旋转的旋转点为x->parent,第二次旋转的旋转点为x->parent->parent
在进行外侧插入的旋转之前先将x->parent->parent(旋转点)的颜色变为红色,将x->parent的颜色变为黑色

1.父节点为左子结点
1.1父节点为左子结点,且父节点的父节点的右子节点(x的叔叔结点)为红色
此时只需要进行 颜色反转即可
在这里插入图片描述

1.2父节点为左子结点,但父节点的父节点的右子节点(x的叔叔结点)不存在或为黑色
如果此时x结点为右子结点(内侧插入)需要进行2次旋转:1.左旋,2.右旋
第一次左旋用x->parent作为旋转点
第二次右旋用x->parent->parent作为旋转点
在这里插入图片描述
如果此时x结点为左子结点(外侧插入)则直接右旋即可
在这里插入图片描述

2.父节点为右子结点
与父节点为左子结点的判断一样与操作是镜像的

2.1父节点为右子结点,且父节点的父节点的左子结点为红结点
颜色反转
在这里插入图片描述
2.2父节点为右子结点,且父节点的父节点的左子结点不存在或为黑结点

如果此时x结点为左子结点(内侧插入)则需要两次旋转1.右旋,2.左旋
第一次右旋用x->parent作为旋转点
第二次左旋用x->parent->parent作为旋转点
在这里插入图片描述
如果此时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    // 无伯父节点,或伯父节点为黑色  
            {  
                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    // 无伯父节点,或伯父节点为黑色  
            {  
                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;    // 根节点永远为黑色  
}  

左旋操作实现
在这里插入图片描述
1.旋转点为x,令y=x->right
2.将y的左子节点变为x的右子结点,(重新构造这段关系:x->right=y->left,y->left->parent=A)
3.将的y父节点更改为x的父节点进行旋转操作(y->parent=x->parent,)
4.让y继承x的地位(重新构造这段关系:如果x是左子结点,x->parent->left=y;如果是右子结点,x->parent->right=y;如果x是根结点:root=y)
5.让x成为y的左子节点:x->parent=y,y->left=A

右旋操作实现
在这里插入图片描述
1.旋转点为x,令y=x->left
2.将y的右子结点m变为的左子结点(重新构造这段关系:x->left=y->right,y->right->parent=x)
3.将y的父节点更改为x的父节点进行右旋操作:y->parent=x->parent
4.让y继承x的位置(重新构造这段关系:如果x是左子节点,x->parent->left=y;
如果是右子结点,x->parent->right=y;如果x是根结点,root=y;
5.让x成为y的右子结点:x->parent=y,y->right=x


// 左旋函数  
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->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->left = y->right;  
    if(y->right != 0)  
        y->right->parent = x;           // 别忘了回马枪设定父节点  
    y->parent = x->parent;  
 
    // 令y完全顶替x的地位(必须将x对其父节点的关系完全接收过来)  
    if(x == root)  
        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;  
}  
©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值