RB-tree源码

本文详细介绍了红黑树的四个性质,包括其构造和内存管理,节点插入时的旋转与换色策略,以及红黑树与AVL树、B+树的区别。通过具体的例子展示了红黑树在插入操作中的完整过程,强调了红黑树在插入和删除效率上的优势,适合大量插入和删除场景。同时,文章分析了删除节点时遵循的规则,确保树的红黑性质得以保持。
摘要由CSDN通过智能技术生成

红黑树

红黑树的四个性质:

(1)每个节点要么红要么黑。

(2)根节点黑色。

(3)每个叶子节点是黑色。【叶子节点指的是NIL或者NULL的叶子节点】。

(4)如果一个节点是红色的,那么它的叶子节点必须是黑色的。

(5)任一节点至NULL(树尾端)的任何路径,所包含的黑节点数必须相同

这些性质强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。主要原因在于,属性4导致了路径不能有两个毗连的红色节点,最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点,根据属性5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。

RM-tree不是严格的平衡树,比AVL-tree弱,然而RB-tree通常能够导致的平衡状态。所以说红黑树是接近平衡的二叉搜索树。

RB-tree的构造和内存管理

RB-tree的构造方式有两种,一种是以现有的RB-tree复制一个新的RB-tree,另一种是产生一棵空树。

 //默认构造函数
 rb_tree(const Compare& comp = Compare())
    : node_count(0), key_compare(comp) { init(); }

  rb_tree(const rb_tree<Key, Value, KeyOfValue, Compare, Alloc>& x) 
    : node_count(0), key_compare(x.key_compare)
  { 
    header = get_node();
    color(header) = __rb_tree_red;
    if (x.root() == 0) {
      root() = 0;
      leftmost() = header;
      rightmost() = header;
    }
    else {
      __STL_TRY {
        root() = __copy(x.root(), header);
      }
      __STL_UNWIND(put_node(header));
      leftmost() = minimum(root());
      rightmost() = maximum(root());
    }
    node_count = x.node_count;
  }
  ~rb_tree() {
    clear();
    put_node(header);
  }

默认构造函数中的init()是实现技巧上的一个关键点:

  void init() {
    header = get_node();//产生一个节点空间,令header指向它
    color(header) = __rb_tree_red; // 令header为红色,以区分header和root 
                                   
    root() = 0; //root() {header->parent;}
    leftmost() = header; //令header的左子节点为自己
    rightmost() = header; //令header的右子节点为自己
  }

树状结构的各种操作,最主要的就是处理边界情况,也就是走到根结点时要有特殊的处理。为了简化处理,SGI STL特别为根结点设计了一个父节点,名为header

下面是header的初始状态 

接下来,每当插入新节点时,不但要依照RB-tree的规则来调整,并且维护header的正确性,使其父节点指向根结点,左子节点指向最小节点,右子节点指向最大节点。

节点插入带来的影响(如何旋转及换色)

为了方便讨论,假设新节点为X,其父节点为P,祖父节点为G,伯父节点为S,曾祖父节点为GG。现在,根据红黑树规则4,X必为红。若P亦为红,则G必为黑。于是,根据X的插入位置及外围节点(S和GG)的颜色,有以下四种考虑。

状况1:S为黑且X为外侧插入------先对P,G做一次单旋转,并更改P,G颜色。

状况2:S为黑且X为内侧插入------先对P,X做一次单旋转并更改X,G颜色,再将结果对G做一次单

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值