• STL源码阅读(六)


    STL源码阅读(六) (SGI STL v3.3)

    type_traits.h (<type_traits> C++11)

    提供编译时类型信息,C++标准直到C++11才正式支持。SGI type_traits.h提供的编译时类型信息很少,
    只提供了_Is_integer判断一个类型是否是整型(bool, char, signed char, unsigned char, wchar_t,
    short, unsigned short, int, unsigned int, long, unsigned long, long long, unsigned long long),
    以及提供了对是否是POD 类型的判断,是否有普通的(trivial)默认构造函数,拷贝构造函数,赋值构造函数和
    析构函数。

    stl_function.h (<functional>)

    unary_function:用来创建单参数函数对象的基类。
    binary_function:用来创建双参数函数对象的基类。
    plus,minus,multiplies,divides,modulus,negate:算术运算函数对象。
    euqal_to,not_equal_to,greater,less,greater_equal,less_equal:关系运算函数对象。
    logical_and,logical_or,logical_not:逻辑运算函数对象。
    unary_negate,binary_negate:仿函数,取反器。
    not1,not2:生成取反器。
    binder1st,binder2nd:仿函数,一元函数绑定器,由一个二元函数和一个参数绑定得到一个一元函数。
    bind1st,bind2st:生成一元函数绑定器。
    unary_compose,binary_compose:非标准。仿函数,函数组合器。
    compose1,compose2:生成函数组合器。
    pointer_to_unary_function,pointer_to_binary_function:仿函数,指向一元函数,二元函数的指针。
    ptr_fun:返回pointer_to_binary_function和pointer_to_unary_function。
    select1st,select2nd:非标准。返回二元组pair的元素。
    project1st,project2nd,constant_void_fun,constant_unary_fun,constant_binary_fun,
    constant0,constant1,constant2,subtractive_rng:非标准。提供这些函数,并没有多大意义。
    mem_fun_t,const_mem_fun_t,mem_fun_ref_t,const_mem_fun_ref_t,
    mem_fun1_t,const_mem_fun1_t,mem_fun1_ref_t,const_mem_fun1_ref_t:成员函数指针包装器。
    mem_fun,mem_fun_ref,mem_fun1,mem_fun1_ref:生成成员函数指针包装器。

    stl_tree.h

    红黑树的实现(以下知识摘于算法导论),用来实现关联容器(set, map, multiset, multimap)。

    红黑树的性质:
    红黑树是一颗二叉搜索树,它在每一个结点上增加了一个存储位来表示结点的颜色,可以是RED或BLACK。通过
    对任何一条从根节点到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其他路径长处2倍,
    因而是近似平衡的。
    一颗红黑树是满足下面红黑性质的二叉搜索树:
    1. 每个结点要么是红色的,要么是黑色的。
    2. 根节点是黑色的。
    3. 每个叶节点(NIL)是黑色的(常常使用一个哨兵结点表示叶节点,或省略此哨兵结点)。
    4. 如果一个结点是红色的,则它的两个子结点都是黑色的。
    5. 对每个结点,从该结点到所有后代叶节点的简单路径上,均包含相同数目的黑色结点。

    // 注意stl_tree所实现的红黑树的树的形式的一些小区别:
    // (1) 头结点不仅指向树根结点,还指向树的最左边的那个结点,以及树的最右边的那个结点。
    // (2) 当要删除的结点有两个孩子时,那么的后继结点重新调整位置链接到被删除结点的位置,而不是将后继结点拷贝到这个位置
    
    // 红黑树颜色约束
    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_iterator),迭代器类型双向迭代器
    _Self& operator++() { _M_increment(); return *this; }
    // 红黑树是一棵二叉搜索树,对任何结点x,其左子树的中的关键字最大不超过x.key,
    // 其右子树中的关键字最小不低于x.key
    void _M_increment() {   // operator++的实现
        // 迭代到比当前结点大的所有结点的中的最小的那个结点
        // 如果右子树存在,那么就是右子树最左边的叶子结点
        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的右子树为止   
            _M_node = __y;
            __y = __y->_M_parent;
          }
        // 当_M_node本身就是个左结点时,那么其父结点便是++迭代到的下一个结点
        // 当_M_node是树最右边的一条边上结点时,_M_node就是树的根结点
        // 当_M_node不是树最右边的一条边上结点时,_M_node就是上面while迭代到的__y
          if (_M_node->_M_right != __y)
            _M_node = __y;
        }
    }
    
    _Self& operator--() { _M_decrement(); return *this; }
    void _M_decrement() {
        // 当前树只有两层的情况,且当前结点为叶节点。考虑状况(1)。
        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) {   // 左子树存在,那么--迭代的下一个结点便是左子树最大的那个结点
          _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;
        }
    }
    
    // 旋转
    
    //        |                                           |
    //        y       <--------rotate_left-----           x
    //       /                                          / 
    //      x   c     ---------rotate_right---->        a   y
    //     /                                              / 
    //    a   b                                           b   c
    
    // 在结点__x做左旋
    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;
    }
    
    // 在结点__x做右旋
    inline void _Rb_tree_rotate_right(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
    {
      _Rb_tree_node_base* __y = __x->_M_left;
      __x->_M_left = __y->_M_right;
      if (__y->_M_right != 0)
        __y->_M_right->_M_parent = __x;
      __y->_M_parent = __x->_M_parent;
    
      if (__x == __root)
        __root = __y;
      else if (__x == __x->_M_parent->_M_right)
        __x->_M_parent->_M_right = __y;
      else
        __x->_M_parent->_M_left = __y;
      __y->_M_right = __x;
      __x->_M_parent = __y;
    }
    
    // 插入结点后,红黑树性质的维护
    // 分为两种情况,所插入的结点的父结点为左结点的情况,和为右节点的情况。
    // 而每种又分为三种情景,见下面代码注释
    
    // __x新插入的结点
    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; // 将父结点的颜色变为黑色
            __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;
    }
    
    // 删除结点,红黑树性质的维护
    // __z待删除结点
    inline _Rb_tree_node_base* _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* __z,
                                 _Rb_tree_node_base*& __root,
                                 _Rb_tree_node_base*& __leftmost,
                                 _Rb_tree_node_base*& __rightmost) {
      _Rb_tree_node_base* __y = __z;
      _Rb_tree_node_base* __x = 0;
      _Rb_tree_node_base* __x_parent = 0;
      if (__y->_M_left == 0)     // __z has at most one non-null child. y == z.
        __x = __y->_M_right;     // __x might be null.
      else
        if (__y->_M_right == 0)  // __z has exactly one non-null child. y == z.
          __x = __y->_M_left;    // __x is not null.
        else {                   // __z has two non-null children.  Set __y to
          __y = __y->_M_right;   //   __z's successor.  __x might be null.
          while (__y->_M_left != 0)
            __y = __y->_M_left;
          __x = __y->_M_right;
        }
      if (__y != __z) {          // relink y in place of z.  y is z's successor
        __z->_M_left->_M_parent = __y; 
        __y->_M_left = __z->_M_left;
        if (__y != __z->_M_right) {
          __x_parent = __y->_M_parent;
          if (__x) __x->_M_parent = __y->_M_parent;
          __y->_M_parent->_M_left = __x;      // __y must be a child of _M_left
          __y->_M_right = __z->_M_right;
          __z->_M_right->_M_parent = __y;
        }
        else
          __x_parent = __y;  
        if (__root == __z)
          __root = __y;
        else if (__z->_M_parent->_M_left == __z)
          __z->_M_parent->_M_left = __y;
        else 
          __z->_M_parent->_M_right = __y;
        __y->_M_parent = __z->_M_parent;
        __STD::swap(__y->_M_color, __z->_M_color);
        __y = __z;
        // __y now points to node to be actually deleted
      }
      else {                        // __y == __z
        __x_parent = __y->_M_parent;
        if (__x) __x->_M_parent = __y->_M_parent;   
        if (__root == __z)
          __root = __x;
        else 
          if (__z->_M_parent->_M_left == __z)
            __z->_M_parent->_M_left = __x;
          else
            __z->_M_parent->_M_right = __x;
        if (__leftmost == __z) 
          if (__z->_M_right == 0)        // __z->_M_left must be null also
            __leftmost = __z->_M_parent;
        // makes __leftmost == _M_header if __z == __root
          else
            __leftmost = _Rb_tree_node_base::_S_minimum(__x);
        if (__rightmost == __z)  
          if (__z->_M_left == 0)         // __z->_M_right must be null also
            __rightmost = __z->_M_parent;  
        // makes __rightmost == _M_header if __z == __root
          else                      // __x == __z->_M_left
            __rightmost = _Rb_tree_node_base::_S_maximum(__x);
      }
      if (__y->_M_color != _S_rb_tree_red) {    // 
        while (__x != __root && (__x == 0 || __x->_M_color == _S_rb_tree_black))
          if (__x == __x_parent->_M_left) {
            _Rb_tree_node_base* __w = __x_parent->_M_right;
            if (__w->_M_color == _S_rb_tree_red) {
              __w->_M_color = _S_rb_tree_black;
              __x_parent->_M_color = _S_rb_tree_red;
              _Rb_tree_rotate_left(__x_parent, __root);
              __w = __x_parent->_M_right;
            }
            if ((__w->_M_left == 0 || 
                 __w->_M_left->_M_color == _S_rb_tree_black) &&
                (__w->_M_right == 0 || 
                 __w->_M_right->_M_color == _S_rb_tree_black)) {
              __w->_M_color = _S_rb_tree_red;
              __x = __x_parent;
              __x_parent = __x_parent->_M_parent;
            } else {
              if (__w->_M_right == 0 || 
                  __w->_M_right->_M_color == _S_rb_tree_black) {
                if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;
                __w->_M_color = _S_rb_tree_red;
                _Rb_tree_rotate_right(__w, __root);
                __w = __x_parent->_M_right;
              }
              __w->_M_color = __x_parent->_M_color;
              __x_parent->_M_color = _S_rb_tree_black;
              if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;
              _Rb_tree_rotate_left(__x_parent, __root);
              break;
            }
          } else {                  // same as above, with _M_right <-> _M_left.
            _Rb_tree_node_base* __w = __x_parent->_M_left;
            if (__w->_M_color == _S_rb_tree_red) {
              __w->_M_color = _S_rb_tree_black;
              __x_parent->_M_color = _S_rb_tree_red;
              _Rb_tree_rotate_right(__x_parent, __root);
              __w = __x_parent->_M_left;
            }
            if ((__w->_M_right == 0 || 
                 __w->_M_right->_M_color == _S_rb_tree_black) &&
                (__w->_M_left == 0 || 
                 __w->_M_left->_M_color == _S_rb_tree_black)) {
              __w->_M_color = _S_rb_tree_red;
              __x = __x_parent;
              __x_parent = __x_parent->_M_parent;
            } else {
              if (__w->_M_left == 0 || 
                  __w->_M_left->_M_color == _S_rb_tree_black) {
                if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;
                __w->_M_color = _S_rb_tree_red;
                _Rb_tree_rotate_left(__w, __root);
                __w = __x_parent->_M_left;
              }
              __w->_M_color = __x_parent->_M_color;
              __x_parent->_M_color = _S_rb_tree_black;
              if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;
              _Rb_tree_rotate_right(__x_parent, __root);
              break;
            }
          }
        if (__x) __x->_M_color = _S_rb_tree_black;
      }
      return __y;
    }
    
    
    template <class _Key, class _Value, class _KeyOfValue, class _Compare, class _Alloc = __STL_DEFAULT_ALLOCATOR(_Value) >
    class _Rb_tree : protected _Rb_tree_base<_Value, _Alloc>;
    // _Rb_tree中维护了一个_M_header指向树的header结点
    // 另外维护了_M_node_count记录树的大小
    // 上面已经列出了红黑树的性质破坏时,正确维护它们的函数。其它增删改查就很容易实现了。

    参考资料

    1. sgi STL
    2. cppreference.com
    3. 算法导论 Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein
    4. CSDN KangRoger的专栏
  • 相关阅读:
    mysql字段使用timestamp类型和默认值CURRENT_TIMESTAMP表示默认为时间,类似mssql的getdate()功能;字段自增
    xmlInitParser 和 xmlCleanupParser 使用详解
    修改虚拟机硬盘的大小
    linux 查看系统进程命令
    linux查看系统信息的命令
    Eclipse快捷键大全(转载)
    获取可执行文件的全路径和所属目录
    dlopen加载c++ 函数及类
    使用LVM在vmware中增大linux的根分区
    查看linux的文件系统是什么格式的(如ext2,ext3,xfs等)?
  • 原文地址:https://www.cnblogs.com/corfox/p/6063303.html
Copyright © 2020-2023  润新知