954 lines
30 KiB
C
954 lines
30 KiB
C
|
#if _MSC_VER > 1000
|
||
|
#pragma once
|
||
|
#endif // _MSC_VER > 1000
|
||
|
|
||
|
template< class Key, class T, class ExtractKey, class CompareKey, class Allocator>
|
||
|
class RBTree
|
||
|
{
|
||
|
public: // Types
|
||
|
typedef RBTree< Key, T, ExtractKey, CompareKey, Allocator> tree_type;
|
||
|
typedef Allocator allocator_type;
|
||
|
|
||
|
typedef Key key_type;
|
||
|
typedef typename allocator_type::value_type value_type;
|
||
|
typedef CompareKey key_compare;
|
||
|
typedef ExtractKey key_extract;
|
||
|
typedef typename allocator_type::pointer pointer;
|
||
|
typedef typename allocator_type::const_pointer const_pointer;
|
||
|
typedef typename allocator_type::reference reference;
|
||
|
typedef typename allocator_type::const_reference const_reference;
|
||
|
typedef typename allocator_type::size_type size_type;
|
||
|
typedef typename allocator_type::difference_type difference_type;
|
||
|
|
||
|
protected: // Types
|
||
|
struct tree_node;
|
||
|
typedef typename Allocator::rebind< tree_node>::other
|
||
|
tree_node_allocator_type;
|
||
|
typedef typename tree_node_allocator_type::pointer tree_node_pointer;
|
||
|
typedef typename tree_node_allocator_type::const_pointer
|
||
|
tree_node_const_pointer;
|
||
|
struct tree_node
|
||
|
{
|
||
|
tree_node_pointer m_pLeft;
|
||
|
tree_node_pointer m_pParent;
|
||
|
tree_node_pointer m_pRight;
|
||
|
value_type m_Value;
|
||
|
bool m_bRed;
|
||
|
|
||
|
tree_node( const tree_node_pointer& pP, const value_type& v, bool bRed)
|
||
|
:m_pLeft( NULL), m_pParent( pP), m_pRight( NULL), m_Value( v),
|
||
|
m_bRed( bRed)
|
||
|
{ }
|
||
|
~tree_node()
|
||
|
{ }
|
||
|
};
|
||
|
template< class TPointer>
|
||
|
struct NextInOrderNode:
|
||
|
public unary_function< TPointer, TPointer>
|
||
|
{
|
||
|
result_type operator()( argument_type Arg, const bool bCouldBeEnd) const
|
||
|
{
|
||
|
if( bCouldBeEnd&& Arg->m_bRed&& Arg->m_pParent->m_pParent== Arg)
|
||
|
Arg= Arg->m_pLeft;
|
||
|
else if( Arg->m_pRight!= NULL)
|
||
|
{
|
||
|
Arg= Arg->m_pRight;
|
||
|
while( Arg->m_pLeft!= NULL)
|
||
|
Arg= Arg->m_pLeft;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TPointer pP;
|
||
|
while( Arg== (pP= Arg->m_pParent)->m_pRight)
|
||
|
Arg= pP;
|
||
|
if( bCouldBeEnd|| Arg->m_pRight!= pP)
|
||
|
Arg= pP;
|
||
|
}
|
||
|
return Arg;
|
||
|
}
|
||
|
};
|
||
|
template< class TPointer>
|
||
|
struct PrevInOrderNode:
|
||
|
public unary_function< TPointer, TPointer>
|
||
|
{
|
||
|
result_type operator()( argument_type Arg, const bool bCouldBeEnd) const
|
||
|
{
|
||
|
if( bCouldBeEnd&& Arg->m_bRed&& Arg->m_pParent->m_pParent== Arg)
|
||
|
Arg= Arg->m_pRight;
|
||
|
else if( Arg->m_pLeft!= NULL)
|
||
|
{
|
||
|
Arg= Arg->m_pLeft;
|
||
|
while( Arg->m_pRight!= NULL)
|
||
|
Arg= Arg->m_pRight;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
TPointer pP;
|
||
|
while( Arg== (pP= Arg->m_pParent)->m_pLeft)
|
||
|
Arg= pP;
|
||
|
if( bCouldBeEnd|| Arg->m_pLeft!= pP)
|
||
|
Arg= pP;
|
||
|
}
|
||
|
return Arg;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
public: // Types
|
||
|
class iterator;
|
||
|
class const_iterator;
|
||
|
class reverse_iterator;
|
||
|
class const_reverse_iterator;
|
||
|
friend class iterator;
|
||
|
class iterator
|
||
|
{
|
||
|
public: // Types
|
||
|
typedef bidirectional_iterator_tag iterator_category;
|
||
|
typedef value_type value_type;
|
||
|
typedef difference_type difference_type;
|
||
|
typedef pointer pointer;
|
||
|
typedef reference reference;
|
||
|
friend class const_iterator;
|
||
|
friend class reverse_iterator;
|
||
|
friend class const_reverse_iterator;
|
||
|
friend class RBTree< Key, T, ExtractKey, CompareKey, Allocator>;
|
||
|
|
||
|
protected:
|
||
|
tree_node_pointer m_pNode;
|
||
|
NextInOrderNode< tree_node_pointer> m_fnNext;
|
||
|
PrevInOrderNode< tree_node_pointer> m_fnPrev;
|
||
|
|
||
|
public:
|
||
|
iterator()
|
||
|
{ }
|
||
|
explicit iterator( const tree_node_pointer& pN)
|
||
|
:m_pNode( pN)
|
||
|
{ }
|
||
|
iterator( const iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
iterator( const reverse_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
reference operator*() const
|
||
|
{ return m_pNode->m_Value; }
|
||
|
pointer operator->() const
|
||
|
{ return &**this; }
|
||
|
iterator& operator++()
|
||
|
{
|
||
|
// end()++ is not valid.
|
||
|
m_pNode= m_fnNext( m_pNode, false);
|
||
|
return (*this);
|
||
|
}
|
||
|
iterator operator++( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
++(*this);
|
||
|
return Temp;
|
||
|
}
|
||
|
iterator& operator--()
|
||
|
{
|
||
|
// end()-- is valid.
|
||
|
m_pNode= m_fnPrev( m_pNode, true);
|
||
|
return (*this);
|
||
|
}
|
||
|
iterator operator--( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
--(*this);
|
||
|
return (Temp);
|
||
|
}
|
||
|
bool operator==( const iterator& Other) const
|
||
|
{ return m_pNode== Other.m_pNode; }
|
||
|
bool operator!=( const iterator& Other) const
|
||
|
{ return m_pNode!= Other.m_pNode; }
|
||
|
};
|
||
|
friend class const_iterator;
|
||
|
class const_iterator
|
||
|
{
|
||
|
public: // Types
|
||
|
typedef bidirectional_iterator_tag iterator_category;
|
||
|
typedef value_type value_type;
|
||
|
typedef difference_type difference_type;
|
||
|
typedef const_pointer pointer;
|
||
|
typedef const_reference reference;
|
||
|
friend class const_reverse_iterator;
|
||
|
friend class RBTree< Key, T, ExtractKey, CompareKey, Allocator>;
|
||
|
|
||
|
protected:
|
||
|
tree_node_const_pointer m_pNode;
|
||
|
NextInOrderNode< tree_node_const_pointer> m_fnNext;
|
||
|
PrevInOrderNode< tree_node_const_pointer> m_fnPrev;
|
||
|
|
||
|
public:
|
||
|
const_iterator()
|
||
|
{ }
|
||
|
explicit const_iterator( const tree_node_const_pointer& pN)
|
||
|
:m_pNode( pN)
|
||
|
{ }
|
||
|
const_iterator( const iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
const_iterator( const const_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
const_iterator( const reverse_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
const_iterator( const const_reverse_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
reference operator*() const
|
||
|
{ return m_pNode->m_Value; }
|
||
|
pointer operator->() const
|
||
|
{ return &**this; }
|
||
|
const_iterator& operator++()
|
||
|
{
|
||
|
// end()++ is not valid.
|
||
|
m_pNode= m_fnNext( m_pNode, false);
|
||
|
return (*this);
|
||
|
}
|
||
|
const_iterator operator++( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
++(*this);
|
||
|
return Temp;
|
||
|
}
|
||
|
const_iterator& operator--()
|
||
|
{
|
||
|
// end()-- is valid.
|
||
|
m_pNode= m_fnPrev( m_pNode, true);
|
||
|
return (*this);
|
||
|
}
|
||
|
const_iterator operator--( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
--(*this);
|
||
|
return (Temp);
|
||
|
}
|
||
|
bool operator==( const const_iterator& Other) const
|
||
|
{ return m_pNode== Other.m_pNode; }
|
||
|
bool operator!=( const const_iterator& Other) const
|
||
|
{ return m_pNode!= Other.m_pNode; }
|
||
|
};
|
||
|
friend class reverse_iterator;
|
||
|
class reverse_iterator
|
||
|
{
|
||
|
public: // Types
|
||
|
typedef bidirectional_iterator_tag iterator_category;
|
||
|
typedef value_type value_type;
|
||
|
typedef difference_type difference_type;
|
||
|
typedef pointer pointer;
|
||
|
typedef reference reference;
|
||
|
friend class iterator;
|
||
|
friend class const_iterator;
|
||
|
friend class const_reverse_iterator;
|
||
|
friend class RBTree< Key, T, ExtractKey, CompareKey, Allocator>;
|
||
|
|
||
|
protected:
|
||
|
tree_node_pointer m_pNode;
|
||
|
PrevInOrderNode< tree_node_pointer> m_fnNext;
|
||
|
NextInOrderNode< tree_node_pointer> m_fnPrev;
|
||
|
|
||
|
public:
|
||
|
reverse_iterator()
|
||
|
{ }
|
||
|
explicit reverse_iterator( const tree_node_pointer& pN)
|
||
|
:m_pNode( pN)
|
||
|
{ }
|
||
|
reverse_iterator( const iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
reverse_iterator( const reverse_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
reference operator*() const
|
||
|
{ return m_pNode->m_Value; }
|
||
|
pointer operator->() const
|
||
|
{ return &**this; }
|
||
|
reverse_iterator& operator++()
|
||
|
{
|
||
|
// rend()++ is not valid.
|
||
|
m_pNode= m_fnNext( m_pNode, false);
|
||
|
return (*this);
|
||
|
}
|
||
|
reverse_iterator operator++( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
++(*this);
|
||
|
return Temp;
|
||
|
}
|
||
|
reverse_iterator& operator--()
|
||
|
{
|
||
|
// rend()-- is valid.
|
||
|
m_pNode= m_fnPrev( m_pNode, true);
|
||
|
return (*this);
|
||
|
}
|
||
|
reverse_iterator operator--( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
--(*this);
|
||
|
return (Temp);
|
||
|
}
|
||
|
bool operator==( const reverse_iterator& Other) const
|
||
|
{ return m_pNode== Other.m_pNode; }
|
||
|
bool operator!=( const reverse_iterator& Other) const
|
||
|
{ return m_pNode!= Other.m_pNode; }
|
||
|
};
|
||
|
friend class const_reverse_iterator;
|
||
|
class const_reverse_iterator
|
||
|
{
|
||
|
public: // Types
|
||
|
typedef bidirectional_iterator_tag iterator_category;
|
||
|
typedef value_type value_type;
|
||
|
typedef difference_type difference_type;
|
||
|
typedef const_pointer pointer;
|
||
|
typedef const_reference reference;
|
||
|
friend class const_iterator;
|
||
|
friend class RBTree< Key, T, ExtractKey, CompareKey, Allocator>;
|
||
|
|
||
|
protected:
|
||
|
tree_node_const_pointer m_pNode;
|
||
|
PrevInOrderNode< tree_node_const_pointer> m_fnNext;
|
||
|
NextInOrderNode< tree_node_const_pointer> m_fnPrev;
|
||
|
|
||
|
public:
|
||
|
const_reverse_iterator()
|
||
|
{ }
|
||
|
explicit const_reverse_iterator( const tree_node_const_pointer& pN)
|
||
|
:m_pNode( pN)
|
||
|
{ }
|
||
|
const_reverse_iterator( const iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
const_reverse_iterator( const const_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
const_reverse_iterator( const reverse_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
const_reverse_iterator( const const_reverse_iterator& Other)
|
||
|
:m_pNode( Other.m_pNode)
|
||
|
{ }
|
||
|
reference operator*() const
|
||
|
{ return m_pNode->m_Value; }
|
||
|
pointer operator->() const
|
||
|
{ return &**this; }
|
||
|
const_reverse_iterator& operator++()
|
||
|
{
|
||
|
// rend()++ is not valid.
|
||
|
m_pNode= m_fnNext( m_pNode, false);
|
||
|
return (*this);
|
||
|
}
|
||
|
const_reverse_iterator operator++( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
++(*this);
|
||
|
return Temp;
|
||
|
}
|
||
|
const_reverse_iterator& operator--()
|
||
|
{
|
||
|
// rend()-- is valid.
|
||
|
m_pNode= m_fnPrev( m_pNode, true);
|
||
|
return (*this);
|
||
|
}
|
||
|
const_reverse_iterator operator--( int)
|
||
|
{
|
||
|
iterator Temp( *this);
|
||
|
--(*this);
|
||
|
return (Temp);
|
||
|
}
|
||
|
bool operator==( const const_reverse_iterator& Other) const
|
||
|
{ return m_pNode== Other.m_pNode; }
|
||
|
bool operator!=( const const_reverse_iterator& Other) const
|
||
|
{ return m_pNode!= Other.m_pNode; }
|
||
|
};
|
||
|
|
||
|
protected: // Variables
|
||
|
tree_node_pointer m_pHead;
|
||
|
size_type m_uiNodes;
|
||
|
key_compare m_key_compare;
|
||
|
key_extract m_key_extract;
|
||
|
tree_node_allocator_type m_allocator;
|
||
|
|
||
|
protected: // Functions
|
||
|
void BuildHeadNode()
|
||
|
{
|
||
|
m_pHead= m_allocator.allocate( 1);
|
||
|
new (&m_pHead->m_pLeft) tree_node_pointer( m_pHead);
|
||
|
new (&m_pHead->m_pParent) tree_node_pointer( NULL);
|
||
|
new (&m_pHead->m_pRight) tree_node_pointer( m_pHead);
|
||
|
new (&m_pHead->m_bRed) bool( true);
|
||
|
}
|
||
|
void DestroyHeadNode()
|
||
|
{
|
||
|
m_pHead->m_pLeft.~list_node_pointer();
|
||
|
m_pHead->m_pParent.~list_node_pointer();
|
||
|
m_pHead->m_pRight.~list_node_pointer();
|
||
|
m_pHead->m_bRed.~bool();
|
||
|
m_allocator.deallocate( m_pHead, 1);
|
||
|
}
|
||
|
void RotateLeft( tree_node_pointer pX)
|
||
|
{
|
||
|
tree_node_pointer pY( pX->m_pRight);
|
||
|
pX->m_pRight= pY->m_pLeft;
|
||
|
if( pY->m_pLeft!= NULL)
|
||
|
pY->m_pLeft->m_pParent= pX;
|
||
|
pY->m_pParent= pX->m_pParent;
|
||
|
if( pX== m_pHead->m_pParent)
|
||
|
m_pHead->m_pParent= pY;
|
||
|
else if( pX== pX->m_pParent->m_pLeft)
|
||
|
pX->m_pParent->m_pLeft= pY;
|
||
|
else
|
||
|
pX->m_pParent->m_pRight= pY;
|
||
|
pY->m_pLeft= pX;
|
||
|
pX->m_pParent= pY;
|
||
|
}
|
||
|
void RotateRight( tree_node_pointer pX)
|
||
|
{
|
||
|
tree_node_pointer pY( pX->m_pLeft);
|
||
|
pX->m_pLeft= pY->m_pRight;
|
||
|
if( pY->m_pRight!= NULL)
|
||
|
pY->m_pRight->m_pParent= pX;
|
||
|
pY->m_pParent= pX->m_pParent;
|
||
|
if( pX== m_pHead->m_pParent)
|
||
|
m_pHead->m_pParent= pY;
|
||
|
else if( pX== pX->m_pParent->m_pRight)
|
||
|
pX->m_pParent->m_pRight= pY;
|
||
|
else
|
||
|
pX->m_pParent->m_pLeft= pY;
|
||
|
pY->m_pRight= pX;
|
||
|
pX->m_pParent= pY;
|
||
|
}
|
||
|
void RecDelete( tree_node_pointer pX)
|
||
|
{
|
||
|
for( tree_node_pointer pY( pX); pY!= NULL; pX= pY)
|
||
|
{
|
||
|
RecDelete( pY->m_pRight);
|
||
|
pY= pY->m_pLeft;
|
||
|
m_allocator.destroy( pX);
|
||
|
m_allocator.deallocate( pX, 1);
|
||
|
}
|
||
|
}
|
||
|
tree_node_pointer lowerbound( const key_type& k) const
|
||
|
{
|
||
|
tree_node_pointer pX( m_pHead->m_pParent);
|
||
|
tree_node_pointer pY( m_pHead);
|
||
|
while( pX!= NULL)
|
||
|
{
|
||
|
if( m_key_compare( m_key_extract( pX->m_Value), k))
|
||
|
pX= pX->m_pRight;
|
||
|
else
|
||
|
{
|
||
|
pY= pX;
|
||
|
pX= pX->m_pLeft;
|
||
|
}
|
||
|
}
|
||
|
return pY;
|
||
|
}
|
||
|
tree_node_pointer upperbound( const key_type& k) const
|
||
|
{
|
||
|
tree_node_pointer pX( m_pHead->m_pParent);
|
||
|
tree_node_pointer pY( m_pHead);
|
||
|
while( pX!= NULL)
|
||
|
{
|
||
|
if( m_key_compare( k, m_key_extract( pX->m_Value)))
|
||
|
{
|
||
|
pY= pX;
|
||
|
pX= pX->m_pLeft;
|
||
|
}
|
||
|
else
|
||
|
pX= pX->m_pRight;
|
||
|
}
|
||
|
return pY;
|
||
|
}
|
||
|
iterator Insert( tree_node_pointer pX,
|
||
|
tree_node_pointer pY, const value_type& V)
|
||
|
{
|
||
|
tree_node_pointer pZ( m_allocator.allocate( 1));
|
||
|
m_allocator.construct( pZ, tree_node( pY, V, true));
|
||
|
++m_uiNodes;
|
||
|
|
||
|
if( pY== m_pHead|| pX!= NULL||
|
||
|
m_key_compare( m_key_extract( V), m_key_extract( pY->m_Value)))
|
||
|
{
|
||
|
pY->m_pLeft= pZ;
|
||
|
if( pY== m_pHead)
|
||
|
{
|
||
|
m_pHead->m_pParent= pZ;
|
||
|
m_pHead->m_pRight= pZ;
|
||
|
}
|
||
|
else if( pY== m_pHead->m_pLeft)
|
||
|
m_pHead->m_pLeft= pZ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pY->m_pRight= pZ;
|
||
|
if( pY== m_pHead->m_pRight)
|
||
|
m_pHead->m_pRight= pZ;
|
||
|
}
|
||
|
|
||
|
for( pX= pZ; pX!= m_pHead->m_pParent&& pX->m_pParent->m_bRed; )
|
||
|
{
|
||
|
if( pX->m_pParent== pX->m_pParent->m_pParent->m_pLeft)
|
||
|
{
|
||
|
pY= pX->m_pParent->m_pParent->m_pRight;
|
||
|
if( pY!= NULL&& pY->m_bRed)
|
||
|
{
|
||
|
pX->m_pParent->m_bRed= false;
|
||
|
pY->m_bRed= false;
|
||
|
pX->m_pParent->m_pParent->m_bRed= true;
|
||
|
pX= pX->m_pParent->m_pParent;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( pX== pX->m_pParent->m_pRight)
|
||
|
{
|
||
|
pX= pX->m_pParent;
|
||
|
RotateLeft( pX);
|
||
|
}
|
||
|
pX->m_pParent->m_bRed= false;
|
||
|
pX->m_pParent->m_pParent->m_bRed= true;
|
||
|
RotateRight( pX->m_pParent->m_pParent);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pY= pX->m_pParent->m_pParent->m_pLeft;
|
||
|
if( pY!= NULL&& pY->m_bRed)
|
||
|
{
|
||
|
pX->m_pParent->m_bRed= false;
|
||
|
pY->m_bRed= false;
|
||
|
pX->m_pParent->m_pParent->m_bRed= true;
|
||
|
pX= pX->m_pParent->m_pParent;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( pX== pX->m_pParent->m_pLeft)
|
||
|
{
|
||
|
pX= pX->m_pParent;
|
||
|
RotateRight( pX);
|
||
|
}
|
||
|
pX->m_pParent->m_bRed= false;
|
||
|
pX->m_pParent->m_pParent->m_bRed= true;
|
||
|
RotateLeft( pX->m_pParent->m_pParent);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
m_pHead->m_pParent->m_bRed= false;
|
||
|
return iterator( pZ);
|
||
|
}
|
||
|
|
||
|
public: // Functions
|
||
|
iterator begin()
|
||
|
{ return iterator( m_pHead->m_pLeft); }
|
||
|
const_iterator begin() const
|
||
|
{ return const_iterator( m_pHead->m_pLeft); }
|
||
|
iterator end()
|
||
|
{ return iterator( m_pHead); }
|
||
|
const_iterator end() const
|
||
|
{ return const_iterator( m_pHead); }
|
||
|
reverse_iterator rbegin()
|
||
|
{ return reverse_iterator( m_pHead->m_pRight); }
|
||
|
const_reverse_iterator rbegin() const
|
||
|
{ return const_reverse_iterator( m_pHead->m_pRight); }
|
||
|
reverse_iterator rend()
|
||
|
{ return reverse_iterator( m_pHead); }
|
||
|
const_reverse_iterator rend() const
|
||
|
{ return const_reverse_iterator( m_pHead); }
|
||
|
size_type size() const
|
||
|
{ return m_uiNodes; }
|
||
|
size_type max_size() const
|
||
|
{ return m_allocator.max_size(); }
|
||
|
bool empty() const
|
||
|
{ return 0== size(); }
|
||
|
key_compare key_comp() const
|
||
|
{ return m_key_compare; }
|
||
|
explicit RBTree( const CompareKey& CmpKey= CompareKey(), const ExtractKey&
|
||
|
ExKey= ExtractKey(), const Allocator& A= Allocator()): m_pHead( NULL),
|
||
|
m_uiNodes( 0), m_key_compare( CmpKey), m_key_extract( ExKey),
|
||
|
m_allocator( A)
|
||
|
{
|
||
|
BuildHeadNode();
|
||
|
}
|
||
|
RBTree( const tree_type& Other): m_pHead( NULL), m_uiNodes( 0),
|
||
|
m_key_compare( Other.m_key_compare), m_key_extract( Other.m_key_extract),
|
||
|
m_allocator( Other.m_allocator)
|
||
|
{
|
||
|
BuildHeadNode();
|
||
|
try {
|
||
|
*this= Other;
|
||
|
} catch( ... ) {
|
||
|
clear();
|
||
|
DestroyHeadNode();
|
||
|
throw;
|
||
|
}
|
||
|
}
|
||
|
~RBTree()
|
||
|
{
|
||
|
clear();
|
||
|
DestroyHeadNode();
|
||
|
}
|
||
|
tree_type& operator=( const tree_type& x)
|
||
|
{
|
||
|
if( this!= &x)
|
||
|
{
|
||
|
erase( begin(), end());
|
||
|
m_key_compare= x.m_key_compare;
|
||
|
m_key_extract= x.m_key_extract;
|
||
|
insert_equal( x.begin(), x.end());
|
||
|
}
|
||
|
return (*this);
|
||
|
}
|
||
|
allocator_type get_allocator() const
|
||
|
{ return m_allocator; }
|
||
|
void swap( const tree_type& x)
|
||
|
{
|
||
|
swap( m_key_compare, x.m_key_compare);
|
||
|
swap( m_key_extract, x.m_key_extract);
|
||
|
if( m_allocator== x.m_allocator)
|
||
|
{
|
||
|
swap( m_pHead, x.m_pHead);
|
||
|
swap( m_uiNodes, x.m_uiNodes);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tree_type Temp( *this);
|
||
|
*this= x;
|
||
|
x= Temp;
|
||
|
}
|
||
|
}
|
||
|
friend void swap( tree_type& x, tree_type& y)
|
||
|
{ x.swap( y); }
|
||
|
pair< iterator, bool> insert_unique( const value_type& x)
|
||
|
{
|
||
|
tree_node_pointer pA( m_pHead->m_pParent);
|
||
|
tree_node_pointer pB( m_pHead);
|
||
|
|
||
|
const key_type XKey( m_key_extract( x));
|
||
|
bool bCmp( true);
|
||
|
while( pA!= NULL)
|
||
|
{
|
||
|
pB= pA;
|
||
|
bCmp= m_key_compare( XKey, m_key_extract( pA->m_Value));
|
||
|
pA= (bCmp? pA->m_pLeft: pA->m_pRight);
|
||
|
}
|
||
|
|
||
|
iterator itP( pB);
|
||
|
if( bCmp)
|
||
|
{
|
||
|
if( itP== begin())
|
||
|
return pair< iterator, bool>( Insert( pA, pB, x), true);
|
||
|
else
|
||
|
--itP;
|
||
|
}
|
||
|
if( m_key_compare( m_key_extract( itP.m_pNode->m_Value), XKey))
|
||
|
return pair< iterator, bool>( Insert( pA, pB, x), true);
|
||
|
return pair< iterator, bool>( itP, false);
|
||
|
}
|
||
|
iterator insert_unique( iterator pP, const value_type& x)
|
||
|
{
|
||
|
return insert_unique( x).first;
|
||
|
}
|
||
|
template< class ForwardIterator>
|
||
|
void insert_unique( ForwardIterator f, ForwardIterator l)
|
||
|
{
|
||
|
while( f!= l)
|
||
|
{
|
||
|
insert_unique( *f);
|
||
|
++f;
|
||
|
}
|
||
|
}
|
||
|
iterator insert_equal( const value_type& x)
|
||
|
{
|
||
|
tree_node_pointer pA( m_pHead->m_pParent);
|
||
|
tree_node_pointer pB( m_pHead);
|
||
|
|
||
|
const key_type XKey( m_key_extract( x));
|
||
|
bool bCmp( true);
|
||
|
while( pA!= NULL)
|
||
|
{
|
||
|
pB= pA;
|
||
|
bCmp= m_key_compare( XKey, m_key_extract( pA->m_Value));
|
||
|
pA= (bCmp? pA->m_pLeft: pA->m_pRight);
|
||
|
}
|
||
|
|
||
|
return iterator( Insert( pA, pB, x));
|
||
|
}
|
||
|
iterator insert_equal( iterator pP, const value_type& x)
|
||
|
{
|
||
|
return insert_equal( x);
|
||
|
}
|
||
|
template< class ForwardIterator>
|
||
|
void insert_equal( ForwardIterator f, ForwardIterator l)
|
||
|
{
|
||
|
while( f!= l)
|
||
|
{
|
||
|
insert_equal( *f);
|
||
|
++f;
|
||
|
}
|
||
|
}
|
||
|
iterator erase( iterator itDel)
|
||
|
{
|
||
|
tree_node_pointer pW;
|
||
|
tree_node_pointer pX;
|
||
|
tree_node_pointer pY( itDel.m_pNode);
|
||
|
tree_node_pointer pZ( pY);
|
||
|
++itDel;
|
||
|
if( pY->m_pLeft== NULL)
|
||
|
pX= pY->m_pRight;
|
||
|
else if( pY->m_pRight== NULL)
|
||
|
pX= pY->m_pLeft;
|
||
|
else
|
||
|
{
|
||
|
pY= pY->m_pRight;
|
||
|
while( pY->m_pLeft!= NULL)
|
||
|
pY= pY->m_pLeft;
|
||
|
pX= pY->m_pRight;
|
||
|
}
|
||
|
tree_node_pointer pXParent( pY);
|
||
|
if( pY!= pZ)
|
||
|
{
|
||
|
pZ->m_pLeft->m_pParent= pY;
|
||
|
pY->m_pLeft= pZ->m_pLeft;
|
||
|
|
||
|
if( pY== pZ->m_pRight)
|
||
|
(pX!= NULL? pX->m_pParent= pXParent= pY: pXParent= pY);
|
||
|
else
|
||
|
{
|
||
|
(pX!= NULL? pX->m_pParent= pXParent= pY->m_pParent: pXParent= pY->m_pParent);
|
||
|
pY->m_pParent->m_pLeft= pX;
|
||
|
pY->m_pRight= pZ->m_pRight;
|
||
|
pZ->m_pRight->m_pParent= pY;
|
||
|
}
|
||
|
|
||
|
if( m_pHead->m_pParent== pZ)
|
||
|
m_pHead->m_pParent= pY;
|
||
|
else if( pZ->m_pParent->m_pLeft== pZ)
|
||
|
pZ->m_pParent->m_pLeft= pY;
|
||
|
else
|
||
|
pZ->m_pParent->m_pRight= pY;
|
||
|
|
||
|
pY->m_pParent= pZ->m_pParent;
|
||
|
const bool bTmp( pY->m_bRed);
|
||
|
pY->m_bRed= pZ->m_bRed;
|
||
|
pZ->m_bRed= bTmp;
|
||
|
pY= pZ;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
(pX!= NULL? pX->m_pParent= pXParent= pY->m_pParent: pXParent= pY->m_pParent);
|
||
|
if( m_pHead->m_pParent== pZ)
|
||
|
m_pHead->m_pParent= pX;
|
||
|
else if( pZ->m_pParent->m_pLeft== pZ)
|
||
|
pZ->m_pParent->m_pLeft= pX;
|
||
|
else
|
||
|
pZ->m_pParent->m_pRight= pX;
|
||
|
|
||
|
if( m_pHead->m_pLeft== pZ)
|
||
|
{
|
||
|
if( pZ->m_pRight== NULL)
|
||
|
m_pHead->m_pLeft= pZ->m_pParent;
|
||
|
else
|
||
|
{
|
||
|
m_pHead->m_pLeft= pX;
|
||
|
while( m_pHead->m_pLeft->m_pLeft!= NULL)
|
||
|
m_pHead->m_pLeft= m_pHead->m_pLeft->m_pLeft;
|
||
|
}
|
||
|
}
|
||
|
if( m_pHead->m_pRight== pZ)
|
||
|
{
|
||
|
if( pZ->m_pLeft== NULL)
|
||
|
m_pHead->m_pRight= pZ->m_pParent;
|
||
|
else
|
||
|
{
|
||
|
m_pHead->m_pRight= pX;
|
||
|
while( m_pHead->m_pRight->m_pRight!= NULL)
|
||
|
m_pHead->m_pRight= m_pHead->m_pRight->m_pRight;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if( !pY->m_bRed)
|
||
|
{
|
||
|
while( pX!= m_pHead->m_pParent&& (pX== NULL|| !pX->m_bRed))
|
||
|
{
|
||
|
if( pX== pXParent->m_pLeft)
|
||
|
{
|
||
|
pW= pXParent->m_pRight;
|
||
|
if( pW->m_bRed)
|
||
|
{
|
||
|
pW->m_bRed= false;
|
||
|
pXParent->m_bRed= true;
|
||
|
RotateLeft( pXParent);
|
||
|
pW= pXParent->m_pRight;
|
||
|
}
|
||
|
if( (pW->m_pLeft== NULL|| !pW->m_pLeft->m_bRed)&&
|
||
|
(pW->m_pRight== NULL|| !pW->m_pRight->m_bRed) )
|
||
|
{
|
||
|
pW->m_bRed= true;
|
||
|
pX= pXParent;
|
||
|
pXParent= pXParent->m_pParent;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( pW->m_pRight== NULL|| !pW->m_pRight->m_bRed)
|
||
|
{
|
||
|
pW->m_pLeft->m_bRed= false;
|
||
|
pW->m_bRed= true;
|
||
|
RotateRight( pW);
|
||
|
pW= pXParent->m_pRight;
|
||
|
}
|
||
|
pW->m_bRed= pXParent->m_bRed;
|
||
|
pXParent->m_bRed= false;
|
||
|
pW->m_pRight->m_bRed= false;
|
||
|
RotateLeft( pXParent);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pW= pXParent->m_pLeft;
|
||
|
if( pW->m_bRed)
|
||
|
{
|
||
|
pW->m_bRed= false;
|
||
|
pXParent->m_bRed= true;
|
||
|
RotateRight( pXParent);
|
||
|
pW= pXParent->m_pLeft;
|
||
|
}
|
||
|
if( (pW->m_pLeft== NULL|| !pW->m_pLeft->m_bRed)&&
|
||
|
(pW->m_pRight== NULL|| !pW->m_pRight->m_bRed) )
|
||
|
{
|
||
|
pW->m_bRed= true;
|
||
|
pX= pXParent;
|
||
|
pXParent= pXParent->m_pParent;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if( pW->m_pLeft== NULL|| !pW->m_pLeft->m_bRed)
|
||
|
{
|
||
|
pW->m_pRight->m_bRed= false;
|
||
|
pW->m_bRed= true;
|
||
|
RotateLeft( pW);
|
||
|
pW= pXParent->m_pLeft;
|
||
|
}
|
||
|
pW->m_bRed= pXParent->m_bRed;
|
||
|
pXParent->m_bRed= false;
|
||
|
pW->m_pLeft->m_bRed= false;
|
||
|
RotateRight( pXParent);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if( pX!= NULL)
|
||
|
pX->m_bRed= false;
|
||
|
}
|
||
|
m_allocator.destroy( pY);
|
||
|
m_allocator.deallocate( pY, 1);
|
||
|
--m_uiNodes;
|
||
|
return itDel;
|
||
|
}
|
||
|
iterator erase( iterator f, iterator l)
|
||
|
{
|
||
|
if( 0== size()|| f!= begin() || l!= end())
|
||
|
{
|
||
|
while( f!= l)
|
||
|
f= erase( f);
|
||
|
return f;
|
||
|
}
|
||
|
clear();
|
||
|
return begin();
|
||
|
}
|
||
|
size_type erase( const key_type& k)
|
||
|
{
|
||
|
const pair< iterator, iterator> EqRng( equal_range( k));
|
||
|
size_type n( 0);
|
||
|
iterator itCur( EqRng.first);
|
||
|
while( itCur!= EqRng.second)
|
||
|
{
|
||
|
++itCur;
|
||
|
++n;
|
||
|
}
|
||
|
erase( EqRng.first, EqRng.second);
|
||
|
return n;
|
||
|
}
|
||
|
void clear()
|
||
|
{
|
||
|
RecDelete( m_pHead->m_pParent);
|
||
|
m_uiNodes= 0;
|
||
|
m_pHead->m_pParent= NULL;
|
||
|
m_pHead->m_pRight= m_pHead->m_pLeft= m_pHead;
|
||
|
}
|
||
|
iterator find( const key_type& k)
|
||
|
{
|
||
|
iterator itLB( lower_bound( k));
|
||
|
return( itLB== end()|| m_key_compare( k, m_key_extract(
|
||
|
itLB.m_pNode->m_Value))? end(): itLB);
|
||
|
}
|
||
|
const_iterator find( const key_type& k) const
|
||
|
{
|
||
|
const_iterator itLB( lower_bound( k));
|
||
|
return( itLB== end()|| m_key_compare( k, m_key_extract(
|
||
|
itLB.m_pNode->m_Value))? end(): itLB);
|
||
|
}
|
||
|
size_type count( const key_type& k) const
|
||
|
{
|
||
|
const pair< const_iterator, const_iterator> EqRng( equal_range( k));
|
||
|
size_type n( 0);
|
||
|
const_iterator itCur( EqRng.first);
|
||
|
while( itCur!= EqRng.second)
|
||
|
{
|
||
|
++itCur;
|
||
|
++n;
|
||
|
}
|
||
|
return n;
|
||
|
}
|
||
|
iterator lower_bound( const key_type& k)
|
||
|
{ return iterator( lowerbound( k)); }
|
||
|
const_iterator lower_bound( const key_type& k) const
|
||
|
{ return const_iterator( lowerbound( k)); }
|
||
|
iterator upper_bound( const key_type& k)
|
||
|
{ return iterator( upperbound( k)); }
|
||
|
const_iterator upper_bound( const key_type& k) const
|
||
|
{ return const_iterator( upperbound( k)); }
|
||
|
pair< iterator, iterator> equal_range( const key_type& k)
|
||
|
{ return pair< iterator, iterator>( lower_bound( k), upper_bound( k)); }
|
||
|
pair< const_iterator, const_iterator> equal_range( const key_type& k) const
|
||
|
{ return pair< const_iterator, const_iterator>( lower_bound( k), upper_bound( k)); }
|
||
|
#if 0
|
||
|
pair< bool, int> InValid( tree_node_pointer pNode, tree_node_pointer pParent, bool bParentRed)
|
||
|
{
|
||
|
pair< bool, int> RightRet( false, 1);
|
||
|
if( pNode->m_pRight!= NULL)
|
||
|
RightRet= InValid( pNode->m_pRight, pNode, pNode->m_bRed);
|
||
|
|
||
|
pair< bool, int> LeftRet( false, 1);
|
||
|
if( pNode->m_pLeft!= NULL)
|
||
|
LeftRet= InValid( pNode->m_pLeft, pNode, pNode->m_bRed);
|
||
|
|
||
|
return pair< bool, int>( pNode->m_pParent!= pParent|| RightRet.first|| LeftRet.first||
|
||
|
RightRet.second!= LeftRet.second|| (bParentRed&& pNode->m_bRed),
|
||
|
RightRet.second+ (pNode->m_bRed? 0: 1));
|
||
|
}
|
||
|
bool valid()
|
||
|
{
|
||
|
if( m_pHead->m_pParent!= NULL)
|
||
|
{
|
||
|
bool bInvalid( InValid( m_pHead->m_pParent, m_pHead, m_pHead->m_bRed).first);
|
||
|
|
||
|
tree_node_pointer pChk= m_pHead->m_pParent;
|
||
|
while( pChk->m_pLeft!= NULL)
|
||
|
pChk= pChk->m_pLeft;
|
||
|
bInvalid|= (pChk!= m_pHead->m_pLeft);
|
||
|
|
||
|
pChk= m_pHead->m_pParent;
|
||
|
while( pChk->m_pRight!= NULL)
|
||
|
pChk= pChk->m_pRight;
|
||
|
bInvalid|= (pChk!= m_pHead->m_pRight);
|
||
|
|
||
|
return !bInvalid;
|
||
|
}
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
#endif
|
||
|
};
|