STL的红黑树实现原理

红黑树本质是一个二叉搜索树,每个节点要么是红色,要么是黑色,加上一些特性,变成平衡二叉搜索树。

红黑树的插入、删除、查找操作的时间复杂度是 O(logN)。

红黑树的高度在 [logN, logN+1]。

规则 1:每个节点不是红色,就是黑色;
规则 2:根节点必须是黑色;
规则 3:如果一个节点是红色,那么它的孩子必须是黑色;
规则 4:任何一个节点向下遍历到其叶子节点,所经过的黑色节点必须相等;
规则 5:空节点必须是黑色;

红黑树的数据结构

struct Rb_tree_node
{
    bool color;
    struct Rb_tree_node *parent;
    struct Rb_tree_node *left;
    struct Rb_tree_node *right;
}

STL中红黑树的定义

typedef bool _Rb_tree_Color_type;
const _Rb_tree_Color_type _S_rb_tree_red = false;
const _Rb_tree_Color_type _S_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 _M_color;  // 颜色
    _Base_ptr _M_parent;   // 父亲节点
    _Base_ptr _M_left;     // 左孩子节点
    _Base_ptr _M_right;    // 右孩子节点
    
    // 找值最小节点
    static _Base_ptr _S_minimum(_Base_ptr __x)
    {
        while (__x->_M_left != 0) __x = __x->_M_left;
        return __x;
    }
    
    // 找值最大节点
    static _Base_ptr _S_maximum(_Base_ptr __x)
    {
        while (__x->_M_right != 0) __x = __x->_M_right;
        return __x;
    }
}

template <class _Value>
struct _Rb_tree_node : public _Rb_tree_node_base
{
    typedef _Rb_tree_node<_Value>* _Link_type;
    _Value _M_value_field;  // 键值
};

基类迭代器

实现基本的寻找下一个元素,上一个元素的功能

// RB-tree 的迭代器-基类
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 _M_node; // 它用来与容器之间产生一个连接关系

  // 供 operator++() 调用,找下一个大的元素
  void _M_increment()
  {
    if (_M_node->_M_right != 0) { // 如果有右子节点,就向右走
      _M_node = _M_node->_M_right;
      while (_M_node->_M_left != 0) // 然后一直往左子树走到底
        _M_node = _M_node->_M_left;
    }
    else {
      _Base_ptr __y = _M_node->_M_parent; // 没有右子节点,找其父节点
      while (_M_node == __y->_M_right) { // 当该节点为其父节点的右子节点,就一直向上找父节点
        _M_node = __y;
        __y = __y->_M_parent;
      }
      if (_M_node->_M_right != __y)
        _M_node = __y;
    }
  }

  // 供 operator--() 调用,找下一个小的元素
  void _M_decrement()
  { // 红色节点,父节点的父节点等于自己
    if (_M_node->_M_color == _S_rb_tree_red &&  
        _M_node->_M_parent->_M_parent == _M_node)
      _M_node = _M_node->_M_right;
    else if (_M_node->_M_left != 0) {                 // 找出 node 的左子树最大值
      _Base_ptr __y = _M_node->_M_left;
      while (__y->_M_right != 0)
        __y = __y->_M_right;
      _M_node = __y;
    }
    else {
      _Base_ptr __y = _M_node->_M_parent;
      while (_M_node == __y->_M_left) {
        _M_node = __y;
        __y = __y->_M_parent;
      }
      _M_node = __y;
    }
  }
};

左旋

// 左旋转 《CLRS》p177
inline void 
_Rb_tree_rotate_left(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
{
  _Rb_tree_node_base* __y = __x->_M_right;
  __x->_M_right = __y->_M_left;
  if (__y->_M_left !=0)
    __y->_M_left->_M_parent = __x;
  __y->_M_parent = __x->_M_parent;

  if (__x == __root)
    __root = __y;
  else if (__x == __x->_M_parent->_M_left)
    __x->_M_parent->_M_left = __y;
  else
    __x->_M_parent->_M_right = __y;
  __y->_M_left = __x;
  __x->_M_parent = __y;
}

插入一个节点

插入一个节点之后,分为4种情况,需要分类讨论,来重新调整红黑树的高度和颜色,使其符合红黑树的定义

// RB-tree 平衡调整  《CLRS》p178
inline void 
_Rb_tree_rebalance(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
{
  __x->_M_color = _S_rb_tree_red;
  while (__x != __root && __x->_M_parent->_M_color == _S_rb_tree_red) {
    if (__x->_M_parent == __x->_M_parent->_M_parent->_M_left) {
      _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_right;
      if (__y && __y->_M_color == _S_rb_tree_red) {
        __x->_M_parent->_M_color = _S_rb_tree_black;   // 黑色1
        __y->_M_color = _S_rb_tree_black;
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
        __x = __x->_M_parent->_M_parent;
      }
      else {
        if (__x == __x->_M_parent->_M_right) {
          __x = __x->_M_parent;
          _Rb_tree_rotate_left(__x, __root);
        }
        __x->_M_parent->_M_color = _S_rb_tree_black;
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
        _Rb_tree_rotate_right(__x->_M_parent->_M_parent, __root);
      }
    }
    else {
      _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_left;
      if (__y && __y->_M_color == _S_rb_tree_red) {
        __x->_M_parent->_M_color = _S_rb_tree_black;
        __y->_M_color = _S_rb_tree_black;
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
        __x = __x->_M_parent->_M_parent;
      }
      else {
        if (__x == __x->_M_parent->_M_left) {
          __x = __x->_M_parent;
          _Rb_tree_rotate_right(__x, __root);
        }
        __x->_M_parent->_M_color = _S_rb_tree_black;
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
        _Rb_tree_rotate_left(__x->_M_parent->_M_parent, __root);
      }
    }
  }
  __root->_M_color = _S_rb_tree_black;
}

我自己写的总结:
在这里插入图片描述
参考视频:red black trees 红黑树 超棒讲解

红黑树的删除

这个有点复杂,下次总结

参考 博客:

https://www.cs.usfca.edu/~galles/visualization/RedBlack.html
https://github.com/steveLauwh/Algorithms/blob/master/Tree/RB-tree/README.md

发布了46 篇原创文章 · 获赞 0 · 访问量 827

猜你喜欢

转载自blog.csdn.net/github_38148039/article/details/103937855