STL 红黑树(Red-Black Tree)源代码分析

转自:http://blog.chinaunix.net/uid-26818262-id-3219065.html

STL提供了许多好用的数据结构与算法,使我们不必为做许许多多的重复劳动。STL里实现了一个树结构-Red-Black Tree,它也是STL里唯一实现的一个树状数据结构,并且它是map, multimap,set,multiset的底层实现,如果学会了Red-Black Tree,那么对我们高效的运用STL是很有帮助的。

1. 什么是红黑树

红黑树是二叉查找树的一种,由于它能够保证树的高度比较底,所以是一种性能较好的查找树。它需要满足以下几条性质: 
1.每个结点或是红的,或是黑的 
2.根结点是黑的 
3.如果一个结点是红的,那么它两个儿子都是黑的 
4.对于每个结点,从该结点到其子孙结点的所有路径上包含数目相同的黑结点

2. 红黑树的操作

红黑树的操作与大多数二叉树操作相同,主要有增加新结点,删除结点,查找结点等等。但是它并不支持直接修改结点,因为结点被修改后会破坏结构,所以在STL中我们也不对一个迭代器的key进行修改。

对于删除与添加操作,因为可能会破坏平衡树的性质,所以我们需要重新对结构进行调整,以使整个树结构保持上述五个性质。由于插入与添加操作涉及比较复杂,我们等到正式讲解STL里实现的时候再详细说明。

因为红黑树可以保证对于N个结点的树,树深度不超过log(2N),所以效率还是相同高的哦。

3. 红黑树结点的定义

下面代码定义了红黑树的结点: 

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

由上面的定义可以看出来,每个结点维护了三个指针:父结点_M_parent,左子结点_M_left,右子结点_M_right,同时还有一个颜色标记_M_color,再就是结点的值_M_value_field。同时可以求得当以某个结点为根的最小与最大结点。因为最小结点一定是最左的子孙结点,最大一定是最右的子孙结点。

4. 红黑树的迭代器定义

迭代器是STL里面非常重要的一部分,这里就不细说了,要说的话几天也说不完。RB Tree里提供的迭代哭是双向迭代器bidirectional_iterator_tag,即可以向前走一步,也可以向后走一步,但是不能像操作指针一样,一下子就走好几步。但考虑到它是树结构,所以它所谓的走向前一个或后一个结点也不是那么简单。还好,STL迭代器里定义了两个函数做到这一步。这其实有点像树的中序遍历,把树的结点排起来,前一个结点就是中序的前一个结点(比它小但是最大的结点),后一个结点就是中序的后一个结点(比它大但是最小的结点)。

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

   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;                            //实现上增加了一个header结点
     } 
   } 

   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;    //header(end())结点的上一个,即为最右子结点 
     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
     } 
   } 
}; 

现在还是看起来有点迷糊,后面分析到红黑树以及header结点的作用时才会有一种恍然大悟的感觉。来看看iterator结口提供了哪些功能。 

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{  _M_node  =  __x} 
   _Rb_tree_iterator( const  iterator &  __it{  _M_node  =  __it . _M_node} 

   reference  operator *()  const  {  return  _Link_type( _M_node) -> _M_value_field} 
#ifndef __SGI_STL_NO_ARROW_OPERATOR 
   pointer  operator ->()  const  {  return  &( operator *());  } 
#endif  /* __SGI_STL_NO_ARROW_OPERATOR */ 

   _Self &  operator ++()  {  _M_increment();  return  * this} 
   _Self  operator ++( int{ 
     _Self  __tmp  =  * this
     _M_increment(); 
     return  __tmp
   } 
    
   _Self &  operator --()  {  _M_decrement();  return  * this} 
   _Self  operator --( int{ 
     _Self  __tmp  =  * this
     _M_decrement(); 
     return  __tmp
   } 
}; 

inline  bool  operator ==( const  _Rb_tree_base_iterator &  __x , 
                        const  _Rb_tree_base_iterator &  __y{ 
   return  __x . _M_node  ==  __y . _M_node
} 

inline  bool  operator !=( const  _Rb_tree_base_iterator &  __x , 
                        const  _Rb_tree_base_iterator &  __y{ 
   return  __x . _M_node  !=  __y . _M_node
} 

可以看到,迭代器的比较是基于指针的比较,并且重载了前置和后置的++,--运算符。它调用的就是_M_decrement()和_M_increment()函数。

5. 红黑树的空间配置器

因为红黑树是动态增长的,所以每次增加或删除结点时都要进行配置,它有一个专用的空间配置器,用来每次申请一个结点的内存或归还一个结点的内存。 

template  < class  _Tp ,  class  _Alloc ,  bool  _S_instanceless > 
class  _Rb_tree_alloc_base  { 
public : 
   typedef  typename  _Alloc_traits < _Tp ,  _Alloc >:: allocator_type  allocator_type
   allocator_type  get_allocator()  const  {  return  _M_node_allocator} 

   _Rb_tree_alloc_base( const  allocator_type &  __a
     :  _M_node_allocator( __a ),  _M_header( 0{} 

protected : 
   typename  _Alloc_traits < _Rb_tree_node < _Tp > ,  _Alloc >:: allocator_type 
            _M_node_allocator
   _Rb_tree_node < _Tp >*  _M_header

   _Rb_tree_node < _Tp >*  _M_get_node() 
     {  return  _M_node_allocator . allocate( 1);  } 
   void  _M_put_node( _Rb_tree_node < _Tp >*  __p
     {  _M_node_allocator . deallocate( __p ,  1);  } 
}; 

// Specialization for instanceless allocators. 
template  < class  _Tp ,  class  _Alloc > 
class  _Rb_tree_alloc_base < _Tp ,  _Alloc ,  true >  { 
public : 
   typedef  typename  _Alloc_traits < _Tp ,  _Alloc >:: allocator_type  allocator_type
   allocator_type  get_allocator()  const  {  return  allocator_type();  } 

   _Rb_tree_alloc_base( const  allocator_type &:  _M_header( 0{} 

protected : 
   _Rb_tree_node < _Tp >*  _M_header

   typedef  typename  _Alloc_traits < _Rb_tree_node < _Tp > ,  _Alloc >:: _Alloc_type 
           _Alloc_type

   _Rb_tree_node < _Tp >*  _M_get_node() 
     {  return  _Alloc_type :: allocate( 1);  } 
   void  _M_put_node( _Rb_tree_node < _Tp >*  __p
     {  _Alloc_type :: deallocate( __p ,  1);  } 
}; 

总体来看也没什么特别有用的信息,_M_get_node()就是申请一个结点的空间,_M_put_node()就是归还了。它调用了allocater()和deallocate(),这是STL里面的内存分配的类。讲这个也可以讲一天。有兴趣的可以看Stl_alloc.h和Stl_construct.h这两个头文件。

6. RB-Tree代码分析

前面讲了这么多废话,终于进行正题了。期待己久的header结点终于出现了。 

template  < class  _Tp ,  class  _Alloc > 
struct  _Rb_tree_base 
{ 
   typedef  _Alloc  allocator_type
   allocator_type  get_allocator()  const  {  return  allocator_type();  } 

   _Rb_tree_base( const  allocator_type &
     :  _M_header( 0{  _M_header  =  _M_get_node();  } 
   ~ _Rb_tree_base()  {  _M_put_node( _M_header);  } 

protected : 
   _Rb_tree_node < _Tp >*  _M_header;       //这个就是头结点,它刚开始就被分配出来 

   typedef  simple_alloc < _Rb_tree_node < _Tp > ,  _Alloc >  _Alloc_type

   _Rb_tree_node < _Tp >*  _M_get_node() 
     {  return  _Alloc_type :: allocate( 1);  } 
   void  _M_put_node( _Rb_tree_node < _Tp >*  __p
     {  _Alloc_type :: deallocate( __p ,  1);  } 
};
一下子也记不住这么多东西,就直接来看主要的代码吧。  

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue ,  class  _Compare , 
           class  _Alloc  =  __STL_DEFAULT_ALLOCATOR( _Value> 
class  _Rb_tree  :  protected  _Rb_tree_base < _Value ,  _Alloc >  { 
   typedef  _Rb_tree_base < _Value ,  _Alloc >  _Base
protected : 
   typedef  _Rb_tree_node_base *  _Base_ptr;  //结点指针
   typedef  _Rb_tree_node < _Value >  _Rb_tree_node;  //结点类型   
   typedef  _Rb_tree_Color_type  _Color_type; //结点颜色 
public : 
   typedef  _Key  key_type;       //key类型 
   typedef  _Value  value_type; //value类型
   typedef  value_type *  pointer;  //以下是迭代器要用的,包括后面定义的iterator
   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

   typedef  typename  _Base :: allocator_type  allocator_type
   allocator_type  get_allocator()  const  {  return  _Base :: get_allocator();  } 

protected : 
#ifdef __STL_USE_NAMESPACES 
   using  _Base :: _M_get_node;        //基类定义的东西 
   using  _Base :: _M_put_node
   using  _Base :: _M_header;             //header结点,实现上使用的 
#endif  /* __STL_USE_NAMESPACES */ 
protected : 

   _Link_type  _M_create_node( const  value_type &  __x) //根据值建一个结点 
   { 
     _Link_type  __tmp  =  _M_get_node(); 
     __STL_TRY  { 
       construct( & __tmp -> _M_value_field ,  __x); 
     } 
     __STL_UNWIND( _M_put_node( __tmp)); 
     return  __tmp
   } 

   _Link_type  _M_clone_node( _Link_type  __x) //复制一个结点,只复制值与颜色 
   { 
     _Link_type  __tmp  =  _M_create_node( __x -> _M_value_field); 
     __tmp -> _M_color  =  __x -> _M_color
     __tmp -> _M_left  =  0
     __tmp -> _M_right  =  0
     return  __tmp
   } 

   void  destroy_node( _Link_type  __p)  //销毁一个结点 
   { 
     destroy( & __p -> _M_value_field); 
     _M_put_node( __p); 
   } 

protected : 
   size_type  _M_node_count// keeps track of size of tree //树结点大小 
   _Compare  _M_key_compare;  //比较器,用于比较两个结点的大小 

   _Link_type &  _M_root()  const  //根结点,header结点的parent是指向根结点的 
     {  return ( _Link_type &_M_header -> _M_parent} 
   _Link_type &  _M_leftmost()  const   //最左子结点,header的左儿子指向最左子结点 
     {  return ( _Link_type &_M_header -> _M_left} 
   _Link_type &  _M_rightmost()  const  //最右子结点,header的右儿子指向最右子结点 
     {  return ( _Link_type &_M_header -> _M_right} 

   static  _Link_type &  _S_left( _Link_type  __x)   //求结点相关信息,看函数名容易知道意思 
     {  return ( _Link_type &)( __x -> _M_left);  } 
   static  _Link_type &  _S_right( _Link_type  __x
     {  return ( _Link_type &)( __x -> _M_right);  } 
   static  _Link_type &  _S_parent( _Link_type  __x
     {  return ( _Link_type &)( __x -> _M_parent);  } 
   static  reference  _S_value( _Link_type  __x
     {  return  __x -> _M_value_field} 
   static  const  _Key &  _S_key( _Link_type  __x
     {  return  _KeyOfValue()( _S_value( __x));  } 
   static  _Color_type &  _S_color( _Link_type  __x
     {  return ( _Color_type &)( __x -> _M_color);  } 

   static  _Link_type &  _S_left( _Base_ptr  __x
     {  return ( _Link_type &)( __x -> _M_left);  } 
   static  _Link_type &  _S_right( _Base_ptr  __x
     {  return ( _Link_type &)( __x -> _M_right);  } 
   static  _Link_type &  _S_parent( _Base_ptr  __x
     {  return ( _Link_type &)( __x -> _M_parent);  } 
   static  reference  _S_value( _Base_ptr  __x
     {  return (( _Link_type) __x) -> _M_value_field} 
   static  const  _Key &  _S_key( _Base_ptr  __x
     {  return  _KeyOfValue()( _S_value( _Link_type( __x )));} 
   static  _Color_type &  _S_color( _Base_ptr  __x
     {  return ( _Color_type &)( _Link_type( __x) -> _M_color);  } 

   static  _Link_type  _S_minimum( _Link_type  __x)  //求最小子结点 
     {  return ( _Link_type)   _Rb_tree_node_base :: _S_minimum( __x);  } 

   static  _Link_type  _S_maximum( _Link_type  __x)  //求最大子结点 
     {  return ( _Link_type_Rb_tree_node_base :: _S_maximum( __x);  } 

public : 
   typedef  _Rb_tree_iterator < value_type ,  reference ,  pointer >  iterator;   //迭代器类型定义 
   typedef  _Rb_tree_iterator < value_type ,  const_reference ,  const_pointer >   const_iterator

#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION 
   typedef  reverse_iterator < const_iterator >  const_reverse_iterator
   typedef  reverse_iterator < iterator >  reverse_iterator
#else  /* __STL_CLASS_PARTIAL_SPECIALIZATION */ 
   typedef  reverse_bidirectional_iterator < iterator ,  value_type ,  reference ,  
                                  difference_type >   reverse_iterator
   typedef  reverse_bidirectional_iterator < const_iterator ,  value_type , 
                                 const_reference ,  difference_type > 
           const_reverse_iterator
#endif  /* __STL_CLASS_PARTIAL_SPECIALIZATION */ 

一直到这里,还没有什么比较难理解的地方,不过我们现在知道了,实现上需要的header结点是这样一个结点,它的父结点是根,它的左右子结点分别指向树中的最左和最右子结点,也就是最小和最大的子结点。

再来看看它的构造函数与析构函数的定义: 

public : 
                                 // allocation/deallocation 
   _Rb_tree() 
     :  _Base( allocator_type ()),  _M_node_count( 0 ),  _M_key_compare() 
     {  _M_empty_initialize();  } 

   _Rb_tree( const  _Compare &  __comp
     :  _Base( allocator_type ()),  _M_node_count( 0 ),  _M_key_compare( __comp
     {  _M_empty_initialize();  } 

   _Rb_tree( const  _Compare &  __comp ,  const  allocator_type &  __a
     :  _Base( __a ),  _M_node_count( 0 ),  _M_key_compare( __comp
     {  _M_empty_initialize();  } 

   _Rb_tree( const  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >&  __x
     :  _Base( __x . get_allocator ()), 
       _M_node_count( 0 ),  _M_key_compare( __x . _M_key_compare) //拷贝构造函数 
   { 
     if ( __x . _M_root()  ==  0
       _M_empty_initialize(); 
     else  { 
       _S_color( _M_header=  _S_rb_tree_red
       _M_root()  =  _M_copy( __x . _M_root (),  _M_header); 
       _M_leftmost()  =  _S_minimum( _M_root()); 
       _M_rightmost()  =  _S_maximum( _M_root()); 
     } 
     _M_node_count  =  __x . _M_node_count
   } 
   ~ _Rb_tree()  {  clear();  } 

private : 
   void  _M_empty_initialize()  { 
     _S_color( _M_header=  _S_rb_tree_red// used to distinguish header from 
                                           // __root, in iterator.operator++ 
     _M_root()  =  0
     _M_leftmost()  =  _M_header
     _M_rightmost()  =  _M_header
   } 

除了拷贝构造函数外,其余构造函数都是直接将header的父指针指向NULL,左右子结点指向自己。拷贝构造函数调用了_M_copy(),它的作用类似于将__x._M_root()为根的树结点复制到_M_header()为根的树结构中。它是通过_M_clone()来完成的。这样就得到了参数一样的树了。析构函数回收所有申请的内存,这里不再讲述。

_Compare  key_comp()  const  {  return  _M_key_compare}    //比较函数 
iterator  begin()  {  return  _M_leftmost();  }   //以下几个函数加上前面定义,可知header 
const_iterator  begin()  const  {  return  _M_leftmost();  }  //得到相关迭代器 
iterator  end()  {  return  _M_header} 
const_iterator  end()  const  {  return  _M_header} 
reverse_iterator  rbegin()  {  return  reverse_iterator( end());  } 
const_reverse_iterator  rbegin()  const  { 
   return  const_reverse_iterator( end()); 
} 
reverse_iterator  rend()  {  return  reverse_iterator( begin());  } 
const_reverse_iterator  rend()  const  { 
   return  const_reverse_iterator( begin()); 
} 
bool  empty()  const  {  return  _M_node_count  ==  0}  //树是否非空 
size_type  size()  const  {  return  _M_node_count}  //树大小 
size_type  max_size()  const  {  return  size_type( - 1);  } 

void  swap( _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >&  __t{ //交换 
   __STD :: swap( _M_header ,  __t . _M_header); 
   __STD :: swap( _M_node_count ,  __t . _M_node_count); 
   __STD :: swap( _M_key_compare ,  __t . _M_key_compare); 
} 

看上面的代码可以知道,header结点就是end()结点,它的左子结点是begin(),从begin()刚好把树遍历一次。树为空时,begin()与end()都指向header,这样就不用对树为空作特殊判断了。可能比较困惑的地方就是rebegin()了,看看它返回的是_M_header,即我们添加的那个header结点,不是它的右儿子么?即最大的那个结点,同理rend()是指向的第一个结点,我们知道一般写代码是这样: 
for(auto itr = mapTree.rbegin(); itr != mapTree.rend(); ++itr) 
看上去好像是有问题,但是如果熟悉迭代器的就能知道,其实反向迭代器在取值是取它下一个结点的值。即正向迭代中上一个结点的值。所以在rend()上一个结点时,它的值己经被遍历到了。

下面代码开始涉及红黑树的操作了,查找树的三大操作就是:查找,添加,删除。查找操作是最简单的,因为它不涉及树结构的改变。所以我们先来看查找操作的代码:

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: find( const  _Key &  __k
{ 
   _Link_type  __y  =  _M_header;       // Last node which is not less than __k. 
   _Link_type  __x  =  _M_root();       // Current node. 

   while ( __x  !=  0)      //树不为空,查找结点 
     if ( ! _M_key_compare( _S_key( __x ),  __k))  //x结点大于或等于k时就向左走 
       __y  =  __x ,  __x  =  _S_left( __x);  //因为x与k可能相同,故先记录下来当前的x 
     else 
       __x  =  _S_right( __x);  //x结点小于k时向右走 

   iterator  __j  =  iterator( __y);   //如果一直向右走,则__j==end(),因为__y不变 
   return ( __j  ==  end() ||  _M_key_compare( __k ,  _S_key( __j . _M_node)))  ? //向左走过的话比较一下 
      end()  :  __j
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: const_iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: find( const  _Key &  __kconst 
{ 
   _Link_type  __y  =  _M_header/* Last node which is not less than __k. */ 
   _Link_type  __x  =  _M_root();  /* Current node. */ 

   while ( __x  !=  0{ 
     if ( ! _M_key_compare( _S_key( __x ),  __k)) 
       __y  =  __x ,  __x  =  _S_left( __x); 
     else 
       __x  =  _S_right( __x); 
   } 
   const_iterator  __j  =  const_iterator( __y);   
   return ( __j  ==  end() ||  _M_key_compare( __k ,  _S_key( __j . _M_node)))  ? 
     end()  :  __j
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: size_type 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: count( const  _Key &  __kconst                                 //有多个少key为__k的结点 
{ 
   pair < const_iterator ,  const_iterator >  __p  =  equal_range( __k); 
   size_type  __n  =  0
   distance( __p . first ,  __p . second ,  __n); 
   return  __n
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: lower_bound( const  _Key &  __k)              //查找第一个不小于或等于key的结点 
{ 
   _Link_type  __y  =  _M_header/* Last node which is not less than __k. */ 
   _Link_type  __x  =  _M_root();  /* Current node. */ 

   while ( __x  !=  0
     if ( ! _M_key_compare( _S_key( __x ),  __k))   //与find()相同 
       __y  =  __x ,  __x  =  _S_left( __x); 
     else 
       __x  =  _S_right( __x); 

   return  iterator( __y);  //不用比较,如果没有比它小的,__y就是end() 
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: const_iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: lower_bound( const  _Key &  __kconst  
{ 
   _Link_type  __y  =  _M_header/* Last node which is not less than __k. */ 
   _Link_type  __x  =  _M_root();  /* Current node. */ 

   while ( __x  !=  0
     if ( ! _M_key_compare( _S_key( __x ),  __k)) 
       __y  =  __x ,  __x  =  _S_left( __x); 
     else 
       __x  =  _S_right( __x); 

   return  const_iterator( __y); 
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: upper_bound( const  _Key &  __k)                  //返回第一个大于key的结点
{ 
   _Link_type  __y  =  _M_header/* Last node which is greater than __k. */ 
   _Link_type  __x  =  _M_root();  /* Current node. */ 

    while ( __x  !=  0
      if ( _M_key_compare( __k ,  _S_key( __x)))  //如果k小于x,有比key大的结点 
        __y  =  __x ,  __x  =  _S_left( __x); 
      else 
        __x  =  _S_right( __x);   //key大于或等于x时,向右走,如果key>所有x,那么__y就是end() 

    return  iterator( __y); 
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: const_iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: upper_bound( const  _Key &  __kconst 
{ 
   _Link_type  __y  =  _M_header/* Last node which is greater than __k. */ 
   _Link_type  __x  =  _M_root();  /* Current node. */ 

    while ( __x  !=  0
      if ( _M_key_compare( __k ,  _S_key( __x))) 
        __y  =  __x ,  __x  =  _S_left( __x); 
      else 
        __x  =  _S_right( __x); 

    return  const_iterator( __y); 
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
inline 
pair < typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: iterator , 
      typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: iterator > 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: equal_range( const  _Key &  __k)   //查找key为__k的一个区间 
{ 
   return  pair < iterator ,  iterator >( lower_bound( __k ),  upper_bound( __k)); 
} 

template  < class  _Key ,  class  _Value ,  class  _KoV ,  class  _Compare ,  class  _Alloc > 
inline 
pair < typename  _Rb_tree < _Key ,  _Value ,  _KoV ,  _Compare ,  _Alloc >:: const_iterator , 
      typename  _Rb_tree < _Key ,  _Value ,  _KoV ,  _Compare ,  _Alloc >:: const_iterator > 
_Rb_tree < _Key ,  _Value ,  _KoV ,  _Compare ,  _Alloc > 
   :: equal_range( const  _Key &  __kconst 
{ 
   return  pair < const_iterator , const_iterator >( lower_bound( __k ), 
                                              upper_bound( __k)); 
} 

可以看到find()函数查找的时候,并不是在查找过程中找到一个key相同的就直接返回了。我们知道左子树都是比根结点小的结点,当相同时,我们再往左子树查找,如果找到,再往左子树查找,这样其实find()返回的就是第一个相同的结点,即在迭代过程中第一个相同的结点。

lower_bound()与find()很类似。但它不用最后比较结点,因为如果这个key大于所有的,那么它在比较的时候会一直向右,那么返回的就是end()。如果它向左走过,就表示有一个key大于等于它了,所以肯定返回的不是end()。

upper_bound()也与find()类似,但是查找第一个大于key的结点。如果x小于或等于key时就向右走,否则向左走。可以看到__M_header的力量真是无穷的。

equal_range()是查找key为k的一段区间,是[lower_bound(), upper_bound()),所以不存在时lower_bound()是与upper_bound()相等的,所以为空。

下面来看看插入的代码,前面和平常的二叉查找树相同,但是由于插入新结点后,可能破坏红黑树的性质,所以在后面对其作了修正。

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: _M_insert( _Base_ptr  __x_ ,  _Base_ptr  __y_ ,  const  _Value &  __v)
//x是新值插入点,y是x的父结点,v是插入结点的值 
{ 
   _Link_type  __x  = ( _Link_type__x_
   _Link_type  __y  = ( _Link_type__y_
   _Link_type  __z

   if ( __y  ==  _M_header ||  __x  !=  0 ||    //y==M_header时树为空 __x不为0只存在insert(iteraotr, val) 
       _M_key_compare( _KeyOfValue()( __v ),  _S_key( __y)))  {  //v小于y,为左儿子 
     __z  =  _M_create_node( __v);   //新建一个结点 
     _S_left( __y=  __z;    // also makes _M_leftmost() = __z 
                                       //    when __y == _M_header  //当树为空时,header->left指向最左 
     if ( __y  ==  _M_header{  //树为空时,向header->parent指向根(现在新增的结点) 
       _M_root()  =  __z
       _M_rightmost()  =  __z;  //header->right指向最右结点(现在只有一个根) 
     } 
     else  if ( __y  ==  _M_leftmost())   //看父结点是不是最左结点,如果是,调整最左结点 
       _M_leftmost()  =  __z;    // maintain _M_leftmost() pointing to min node 
   } 
   else  { 
     __z  =  _M_create_node( __v);  //新建一个结点   
     _S_right( __y=  __z;   //为右儿子 
     if ( __y  ==  _M_rightmost())   //如果父结点为最右结点,调整最右结点 
       _M_rightmost()  =  __z;   // maintain _M_rightmost() pointing to max node 
   } 
   _S_parent( __z=  __y;   //更新结点信息 
   _S_left( __z=  0
   _S_right( __z=  0
   _Rb_tree_rebalance( __z ,  _M_header -> _M_parent);  //调整树结构,使其符合RB-Tree性质 
   ++ _M_node_count;   //将结点个数+1 
   return  iterator( __z); 
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: iterator 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: insert_equal( const  _Value &  __v)  //插入一个值,允许值相同 
{ 
   _Link_type  __y  =  _M_header
   _Link_type  __x  =  _M_root(); 
   while ( __x  !=  0{ 
     __y  =  __x
     __x  =  _M_key_compare( _KeyOfValue()( __v ),  _S_key( __x))  ? //v小于x,向左走,否则向右走 
             _S_left( __x:  _S_right( __x); 
   } 
   return  _M_insert( __x ,  __y ,  __v);  //找到位置,插入__x是NULL 
} 


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)  //插入一个值v,不允许重复 
{ 
   _Link_type  __y  =  _M_header
   _Link_type  __x  =  _M_root(); 
   bool  __comp  =  true
   while ( __x  !=  0{ 
     __y  =  __x
     __comp  =  _M_key_compare( _KeyOfValue()( __v ),  _S_key( __x));  //v小于x向左走,否则向左走 
     __x  =  __comp  ?  _S_left( __x:  _S_right( __x); 
   } 
   iterator  __j  =  iterator( __y);   
   if ( __comp) //如果__comp为true,表示最后一步中v小于x,即存在一个大于或等于v的结点
     if ( __j  ==  begin())     //但是它如果比最小的还小,那么肯定不存在相等的结点 
       return  pair < iterator , bool >( _M_insert( __x ,  __y ,  __v ),  true); 
     else 
       -- __j;  //大于或等于它的那个结点 
   if ( _M_key_compare( _S_key( __j . _M_node ),  _KeyOfValue()( __v)))  //没有相同的结点时插入 
     return  pair < iterator , bool >( _M_insert( __x ,  __y ,  __v ),  true); 
   return  pair < iterator , bool >( __j ,  false); //否则直接返回该结点即可 
} 


template  < class  _Key ,  class  _Val ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key ,  _Val ,  _KeyOfValue ,  _Compare ,  _Alloc >:: iterator 
_Rb_tree < _Key ,  _Val ,  _KeyOfValue ,  _Compare ,  _Alloc > 
   :: insert_unique( iterator  __position ,  const  _Val &  __v
{ 
   if ( __position . _M_node  ==  _M_header -> _M_left{  // begin() 
     if ( size()  >  0  && 
         _M_key_compare( _KeyOfValue()( __v ),  _S_key( __position . _M_node))) 
       return  _M_insert( __position . _M_node ,  __position . _M_node ,  __v); 
     // first argument just needs to be non-null 
     else 
       return  insert_unique( __v ). first
   }  else  if ( __position . _M_node  ==  _M_header{  // end() 
     if ( _M_key_compare( _S_key( _M_rightmost ()),  _KeyOfValue()( __v))) 
       return  _M_insert( 0 ,  _M_rightmost (),  __v); 
     else 
       return  insert_unique( __v ). first
   }  else  { 
     iterator  __before  =  __position
     -- __before
     if ( _M_key_compare( _S_key( __before . _M_node ),  _KeyOfValue()( __v)) 
         &&  _M_key_compare( _KeyOfValue()( __v ),  _S_key( __position . _M_node)))  { 
       if ( _S_right( __before . _M_node==  0
         return  _M_insert( 0 ,  __before . _M_node ,  __v); 
       else 
         return  _M_insert( __position . _M_node ,  __position . _M_node ,  __v); 
     // first argument just needs to be non-null 
     }  else 
       return  insert_unique( __v ). first
   } 
} 

template  < class  _Key ,  class  _Val ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Val , _KeyOfValue , _Compare , _Alloc >:: iterator 
_Rb_tree < _Key , _Val , _KeyOfValue , _Compare , _Alloc > 
   :: insert_equal( iterator  __position ,  const  _Val &  __v
{ 
   if ( __position . _M_node  ==  _M_header -> _M_left{  // begin() 
     if ( size()  >  0  && 
         ! _M_key_compare( _S_key( __position . _M_node ),  _KeyOfValue()( __v))) 
       return  _M_insert( __position . _M_node ,  __position . _M_node ,  __v); 
     // first argument just needs to be non-null 
     else 
       return  insert_equal( __v); 
   }  else  if ( __position . _M_node  ==  _M_header{ // end() 
     if ( ! _M_key_compare( _KeyOfValue()( __v ),  _S_key( _M_rightmost()))) 
       return  _M_insert( 0 ,  _M_rightmost (),  __v); 
     else 
       return  insert_equal( __v); 
   }  else  { 
     iterator  __before  =  __position
     -- __before
     if ( ! _M_key_compare( _KeyOfValue()( __v ),  _S_key( __before . _M_node)) 
         &&  ! _M_key_compare( _S_key( __position . _M_node ),  _KeyOfValue()( __v)))  { 
       if ( _S_right( __before . _M_node==  0
         return  _M_insert( 0 ,  __before . _M_node ,  __v); 
       else 
         return  _M_insert( __position . _M_node ,  __position . _M_node ,  __v); 
     // first argument just needs to be non-null 
     }  else 
       return  insert_equal( __v); 
   } 
} 

#ifdef __STL_MEMBER_TEMPLATES  

template  < class  _Key ,  class  _Val ,  class  _KoV ,  class  _Cmp ,  class  _Alloc > 
   template < class  _II > 
void  _Rb_tree < _Key , _Val , _KoV , _Cmp , _Alloc > 
   :: insert_equal( _II  __first ,  _II  __last) //插入一段区间值 
{ 
   for ( ;  __first  !=  __last++ __first
     insert_equal( * __first); 
} 

template  < class  _Key ,  class  _Val ,  class  _KoV ,  class  _Cmp ,  class  _Alloc > 
   template < class  _II > 
void  _Rb_tree < _Key , _Val , _KoV , _Cmp , _Alloc > 
   :: insert_unique( _II  __first ,  _II  __last{  //插入一段区间值 
   for ( ;  __first  !=  __last++ __first
     insert_unique( * __first); 
} 

#else  /* __STL_MEMBER_TEMPLATES */ 

template  < class  _Key ,  class  _Val ,  class  _KoV ,  class  _Cmp ,  class  _Alloc > 
void 
_Rb_tree < _Key , _Val , _KoV , _Cmp , _Alloc > 
   :: insert_equal( const  _Val *  __first ,  const  _Val *  __last
{ 
   for ( ;  __first  !=  __last++ __first) //插入一段区间值 
     insert_equal( * __first); 
} 

template  < class  _Key ,  class  _Val ,  class  _KoV ,  class  _Cmp ,  class  _Alloc > 
void 
_Rb_tree < _Key , _Val , _KoV , _Cmp , _Alloc > 
   :: insert_equal( const_iterator  __first ,  const_iterator  __last) //插入一段区间值 
{ 
   for ( ;  __first  !=  __last++ __first
     insert_equal( * __first); 
} 

template  < class  _Key ,  class  _Val ,  class  _KoV ,  class  _Cmp ,  class  _Alloc > 
void 
_Rb_tree < _Key , _Val , _KoV , _Cmp , _Alloc > 
   :: insert_unique( const  _Val *  __first ,  const  _Val *  __last) //插入一段区间值 
{ 
   for ( ;  __first  !=  __last++ __first
     insert_unique( * __first); 
} 

template  < class  _Key ,  class  _Val ,  class  _KoV ,  class  _Cmp ,  class  _Alloc > 
void  _Rb_tree < _Key , _Val , _KoV , _Cmp , _Alloc > 
   :: insert_unique( const_iterator  __first ,  const_iterator  __last)  //插入一段区间值 
{ 
   for ( ;  __first  !=  __last++ __first
     insert_unique( * __first); 
} 

这么多insert,其实主要的还是_M_insert函数的调用,其余函数先和其它的查找树一样,先找到插入点,然后再进行插入,插入后再调整树结构,使其符合红黑树的性质。注意在_M_insert()中新增加的结点颜色还没有被赋值,它是在_Rb_tree_rebalance()函数中被赋值为红结点,新增加的结点初始颜色都是红色。

在讨论_Rb_tree_rebalance()之前,我们要先来看看两个函数,即左旋和右旋。故名思义,就是对于子结点和其父结点围着边向左旋转或向右旋转。当然,它会改变树结点,但经过调整后它并不会改变查找树的性质,即左子树永远比根结点的值小,右子树的结点不会比根结点小。

看下图:X,Y代表结点,A,B,C代表子树,子树可能为空。 
 左旋右旋图

inline  void 
_Rb_tree_rotate_left( _Rb_tree_node_base *  __x ,  _Rb_tree_node_base *&  __root) //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;  //将y放到x的位置 

   if ( __x  ==  __root)  //如果x原来是根,现在变成y了 
     __root  =  __y
   else  if ( __x  ==  __x -> _M_parent -> _M_left)  //如果x原来是左儿子 
     __x -> _M_parent -> _M_left  =  __y;  
   else   //原来是右儿子 
     __x -> _M_parent -> _M_right  =  __y
   __y -> _M_left  =  __x;  //修改指针 
   __x -> _M_parent  =  __y
} 

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; //将y的右儿子变为x的左儿子 
   if ( __y -> _M_right  !=  0)  //如果不为空,修改父指针 
     __y -> _M_right -> _M_parent  =  __x
   __y -> _M_parent  =  __x -> _M_parent;  //将y链接到x的parent上 

   if ( __x  ==  __root)  //如果x原来为根,现在变成了y 
     __root  =  __y
   else  if ( __x  ==  __x -> _M_parent -> _M_right)  //如果x原来是右儿子 
     __x -> _M_parent -> _M_right  =  __y
   else   //x原来为左儿子 
     __x -> _M_parent -> _M_left  =  __y
   __y -> _M_right  =  __x;  //修改指针 
   __x -> _M_parent  =  __y
} 

可以看到,左旋和右旋其实是一对互逆的过程。从图中也可以看到,不论是左旋还中右旋,它们还是满足左子树结点一定比根小,右子树结点一定不比根小的规律。从红黑树的性质来看,当插入一个结点后,唯一可能不满足的条件就是2和3了。2是因为当空树插入一个结点时,因为初始颜色为红,而3就很显然了。现在我们就需要通过从下往上来调整树结构,使其满足其性质。OK,来看看代码:

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{   //case_1  
       _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{   //case_2  
           __x  =  __x -> _M_parent
           _Rb_tree_rotate_left( __x ,  __root); 
         } 
         __x -> _M_parent -> _M_color  =  _S_rb_tree_black;    //case_3 
         __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{  //case_4  
         __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//case_5  
           __x  =  __x -> _M_parent
           _Rb_tree_rotate_right( __x ,  __root); 
         } 
         __x -> _M_parent -> _M_color  =  _S_rb_tree_black;    //case_6 
         __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;   //根结点颜色一定是黑的 
} 

OK,看最后一行,性质2满足了。唯一可能不满足的现在就是性质3了。关于调整总共是有六种情况,但这六种情况是对称的,所以总得来说我们分析三种情况就可以了。记住第一个while循环的条件,它结束的条件第一个很好理解,为根的时候父结点是_M_header了,所以就看父结点是红才继续,如果有调整结构的时候我们一直保证红黑树的性,即我们现在不满足的条件就是性质3,那么只有父结点是黑,那么所有条件都是满足的。

这六种情况,我用case_x在代码中表示出来了。先看case_1.case_1调整前后对经如下图: 
xp表示x的parent结点,xpp表示x的parent的parent结点 
CA_1
可以看到,它并不改变树结构,只是改变结点颜色,由于它将那个黑色结点下沉,所以其它性质依然不会被破坏,唯一可能不满足的还是性质3,即红结点的儿子结点也有红色的。当时,经过case_1后,结点向上走了两层。 
其实case_2与case_3是在一起处理的,从代码中也可以看出来,case_2后,会继续执行case_3,这是因为case_2经过处理刚好与case_3完全一样。case_2, case_3如下图所示: 
CAS3

case_2经过左旋变为case_3时,x还是在同一层上面,而再经过处理后,x的父结点己经是黑色了,也就是while循环条件不满足了,所以从这也可以看出,在RB-Tree调整中,最多经过两次旋转就结束了。case_4,5,6与case_1,2,3就是一个相反的过程了。

最后来看RB Tree最后一个操作——删除,下面这段代码很简单,阅读起来没有问题:

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
void  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: _M_erase( _Link_type  __x)  //删掉x为根的子树,并不会改变树的性质,故不需要rebalance 
{ 
                                 // erase without rebalancing 
   while ( __x  !=  0{ 
     _M_erase( _S_right( __x));   
     _Link_type  __y  =  _S_left( __x); 
     destroy_node( __x); 
     __x  =  __y
   } 
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
void  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: erase( iterator  __first ,  iterator  __last)  //删除整个迭代区间内结点 
{ 
   if ( __first  ==  begin()  &&  __last  ==  end()) 
     clear(); 
   else 
     while ( __first  !=  __lasterase( __first ++); 
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
void  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: erase( const  _Key *  __first ,  const  _Key *  __last)   //删除区间内的key 
{ 
   while ( __first  !=  __lasterase( * __first ++); 
} 

执行删除的代码在这里: 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
inline  void  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc > 
   :: erase( iterator  __position)   //删除迭代器指向的结点 
{ 
   _Link_type  __y  = 
    ( _Link_type_Rb_tree_rebalance_for_erase( __position . _M_node , 
                                               _M_header -> _M_parent , 
                                               _M_header -> _M_left , 
                                               _M_header -> _M_right); 
   destroy_node( __y); 
   -- _M_node_count
} 

template  < class  _Key ,  class  _Value ,  class  _KeyOfValue , 
           class  _Compare ,  class  _Alloc > 
typename  _Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: size_type 
_Rb_tree < _Key , _Value , _KeyOfValue , _Compare , _Alloc >:: erase( const  _Key &  __x) //删除key为x的结点 
{ 
   pair < iterator , iterator >  __p  =  equal_range( __x); //把key为x的迭代区间求出来 
   size_type  __n  =  0
   distance( __p . first ,  __p . second ,  __n); 
   erase( __p . first ,  __p . second); //一个一个删除 
   return  __n
} 

上面的代码还是不痛不痒,删除区间的时候是一个一个删除的,在删除的时候我们主要调用的就是_Rb_tree_rebalance_for_erase()函数,它有四个参数,要删除的结点,根,最左结点和最右结点。下面是_Rb_tree_rebalance_for_erase函数的定义。

我们想想平常的二叉查找树中是怎么删除一个结点的:
1. 如果结点至多只有一个子结点,那么将其链接到父结点
2.否则找到其后继结点,先删除后继,再将后继结点的值放到原来要删除的结点中。

恩,很长的一段代码:

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;  //y操作后指向是要删除的结点
   _Rb_tree_node_base *  __x  =  0;
   _Rb_tree_node_base *  __x_parent  =  0;
   if ( __y -> _M_left  ==  0)    //左子树为空时
     __x  =  __y -> _M_right;     //x指向y的右子树,x可能是NULL
   else
     if ( __y -> _M_right  ==  0) //右子树为空时 .
       __x  =  __y -> _M_left;   //x指向左子树,x一定不为空,前一个判断判断过了
     else  {           //当z的左右子树都不为空时
       __y  =  __y -> _M_right;  //令y指向z的后继,x为后继的右子树,可能为NULL
       while ( __y -> _M_left  !=  0)
         __y  =  __y -> _M_left;
       __x  =  __y -> _M_right;   //x可能为空
     }
   if ( __y  !=  __z{        //如果y!=z,现在y是原来z的后继
     //将z的左子树接到y的左子树上(y的左子树之前一定是NULL)
     __z -> _M_left -> _M_parent  =  __y
     __y -> _M_left  =  __z -> _M_left;
     if ( __y  !=  __z -> _M_right{ //如果后继结点不是z的右儿子
       __x_parent  =  __y -> _M_parent; //先将y的parent记录下来
       if ( __x__x -> _M_parent  =  __y -> _M_parent; //如果x不是NULL,将它指向y的父结点
       __y -> _M_parent -> _M_left  =  __x;     //y原来是左儿子
       __y -> _M_right  =  __z -> _M_right; //将原来的z的右子树接到y的右子树上面
       __z -> _M_right -> _M_parent  =  __y;
     }
     else    //如果y=-z,z至少有一个子树为空
       __x_parent  =  __y;  
     if ( __root  ==  __z) //如果要删除的是根
       __root  =  __y;  //新根结点
     else  if ( __z -> _M_parent -> _M_left  ==  __z)  //如果原来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  =  __z;  //y指向最后要删除的结点
     // __y now points to node to be actually deleted
   }
   else  {         //删除的结点至多只有一个儿子
     __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)       //如果它的右儿子也为空
         __leftmost  =  __z -> _M_parent; //新的最左结点就是它的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)         //它的左儿子也为空
         __rightmost  =  __z -> _M_parent;  //新的最右结点是它的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{           //case_1
           __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))  {       //case_2
           __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{         //case_3
             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;          //case_4
           __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;
}

同样,从上面那个if (__y->_M_color != _S_rb_tree_red之前,操作代码与二叉查找树是一样的,就是判断,再链接。但是这样操作可能会破坏红黑树的性质,所以后面就再做了调整,为什么有这个if判断呢?这是因为如果删除的是一个红结点,RB-Tree的性质还是符合的:
1. 从各点到任何一个叶结点经过的黑结点个数相同(删除之前就满足的条件)
2. 不存在两个相邻的红结点(删除之前满足的条件)
3. 根结点是黑的(原来根结点是黑的,删的是红结点,所以不可能被删除的是根)

由于被删除的结点是一个黑结点,所以任何经过x的路径上的黑结点个数将会少1. 所以我们先x视为还有一重黑色。其改变方法总共是八种,也是两两对称的。根据代码中的case_1,2,3,4,我们直接看图是怎么旋转的(橙色结点表示颜色可能是红色也可能是黑色):
case_1: x的兄弟结点是红色的:
1 
case_2:x的兄弟结点是黑色的,且两个儿子也是黑色的
2 
case_3:x的兄弟结点是红色的,且左儿子是黑色的,右儿子是红色的
3 
case_4:x的兄弟结点是红色的,且右儿子是红色的,左儿子颜色随意
4

x一直是指向具有双重黑色的结点,它也有一个很好的性质,即最多做三次旋转就会结束。对比上面的图我们可快可以知道红黑的在删除时是怎么维持结点的性质的。

因为红黑树是map, multimap, set, multiset的底层实现,所以上述代码里基本上包含了所有上述操作的集合。代码挺长,想要高效的运用STL,虽然不要通读其源码,但是读源码还是能给人很多好的思路,如红黑树实现中header结点,它使人们对许多特殊情况都不再需要判断了。不过在读STL算法与数据结构的源代码之前,你需要了解的就是STL里的迭代器和内存分配器的原理,这样读起来才不会让人感觉到云里雾里,同时你还需要了解其数据结构的实现原理,这样就能事半功倍了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值