无敌重要的【RB-tree】

本文介绍了关联式容器中的RB-tree(红黑树),它作为set和map等容器的底层数据结构。红黑树是一种二叉搜索树,具有特定的颜色规则以保证平衡。文章详细阐述了红黑树的插入操作,包括不同情况下的调整策略,并提到了迭代器设计的重要性,特别是其双向但不支持随即定位的特点。
摘要由CSDN通过智能技术生成

关联式容器

  • 分为set 和map两大类及其衍生体。所有容器底层均是RB-tree红黑树(这也是一个独立容器,但是不开放给外界使用);此外还提供hash table 及以它为底层完成的hash_set , hash_map , hash_multiset , hash_multimap

  • 每笔数据(每个元素)都有一个键值key和一个实值value,内部按照key大小按照某种规则放在适当位置,故没有所谓的头尾。

  • 一些基本术语
    在这里插入图片描述

  • 二叉搜索树:插入删除
    在这里插入图片描述在这里插入图片描述

  • 平衡二叉搜索树:插入删除更麻烦,但搜索节省25%左右时间

  • AVL tree:深度O(logN)
    在这里插入图片描述

  • 单旋转
    在这里插入图片描述

  • 双旋转
    在这里插入图片描述

RB-tree

  • 是二叉搜索树;节点非红即黑;根节点黑色;若节点红,子节点必黑;任一节点至NULL(树尾端)的任何路径,所含黑节点树必然相同
    在这里插入图片描述

  • 插入节点
    在这里插入图片描述

    • 状况一:
      在这里插入图片描述
    • 状况二:第二次调整是因为不满足根节点是黑色的规则?还是为了相对平衡
      在这里插入图片描述
    • 状况三:
      在这里插入图片描述
    • 状况四:
      在这里插入图片描述
  • 一个由上而下的程序
    在这里插入图片描述
    之后节点35的插入就很单纯了:要么直接插入,要么插入后再一次旋转
    在这里插入图片描述

  • 迭代器设计非常关键。SGI 将迭代器设计为两层(与slist相似): _ rb_tree node继承自 rb_tree _node _base, _ _rb_tree node iterator继承自 rb_tree _node _base __iterator.
    在这里插入图片描述
    双向迭代器,但不具备随即定位的能力。

  • ++和–中令人费解的边界操作:
    在这里插入图片描述
    其中header(特别为根节点再设计的)的定义如下:
    在这里插入图片描述

  • 注意,真实实现时,外侧只依次调整颜色,内侧才进行双旋,和上面的不一样
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

#ifndef __SGI_STL_INTERNAL_TREE_H
#define __SGI_STL_INTERNAL_TREE_H

#include <stl_algobase.h>
#include <stl_alloc.h>
#include <stl_construct.h>
#include <stl_function.h>

__STL_BEGIN_NAMESPACE 

typedef bool __rb_tree_color_type;
const __rb_tree_color_type __rb_tree_red = false; //红为0,黑为1
const __rb_tree_color_type __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 color; //节点颜色
  base_ptr parent; //父节点
  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;//结点值
};

//基层迭代器
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 node;//用来与容器之间产生一个联结

  //只有operator++调用了此函数
  //该函数对着画的图就能看懂了,若无右节点且身为左子树,父节点即为所求
  //若为右子树,则向上追溯到不为右子树的点,然后转向其父节点(拐个弯)即为所求
  void increment()
  {
    if (node->right != 0) {//有右节点
      node = node->right;//下一个就是右子树的最左节点
      while (node->left != 0)
        node = node->left;
    }
    else {
      base_ptr y = node->parent;
      while (node == y->right) {//该结点不为右节点
        node = y;
        y = y->parent;
      }
      if (node->right != y)//右子节点不等于父节点为了应付根节点情况
        node = y;//父节点即为所求
    }
  }

  void decrement()
  {
    //当node为header时,即end(),header右节点为mostright,指向max节点
    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)
        y = y->right;
      node = y;
    }
    else {
      base_ptr y = node->parent;
      while (node == y->left) {
        node = y;
        y = y->parent;
      }
      node = y;
    }
  }
};

//正规迭代器
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; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */

  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;
  }
};

inline bool operator==(const __rb_tree_base_iterator& x,
                       const __rb_tree_base_iterator& y) {
  return x.node == y.node;
}

inline bool operator!=(const __rb_tree_base_iterator& x,
                       const __rb_tree_base_iterator& y) {
  return x.node != y.node;
}

#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION

inline bidirectional_iterator_tag
iterator_category(const __rb_tree_base_iterator&) {
  return bidirectional_iterator_tag();
}

inline __rb_tree_base_iterator::difference_type*
distance_type(const __rb_tree_base_iterator&) {
  return (__rb_tree_base_iterator::difference_type*) 0;
}

template <class Value, class Ref, class Ptr>
inline Value* value_type(const __rb_tree_iterator<Value, Ref, Ptr>&) {
  return (Value*) 0;
}

#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */

//类似右旋,不再赘述
inline void 
__rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
  __rb_tree_node_base* y = x->right;
  x->right = y->left;
  if (y->left !=0)
    y->left->parent = x;
  y->parent = x->parent;

  if (x == root)
    root = y;
  else if (x =&#
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值