红黑树
概念
它是一个平衡树,查找效率为O(log2n),中序遍历时为有序序列。我只实现了unique_insert,对于equal_insert,stl是把键值相同的节点当做到该节点的右孩子。所以遍历muti_map时遍历一个键值对应的多个时值的时候,应该先find找到第一个K的位置,在调用count函数找到该K有多少个键值相同的节点。从第一个find返回第一个key位置的迭代器,然后每遍历一个节点,++先后移一次即可。
特性
- 每个节点,不是红色就是黑色
- 不能有连续俩个红色节点,即父子节点不能同为红色
- 根节点必须是黑色的
- 任意一条路径上的黑色节点数目都相同
- NULL节点颜色是黑色(这个可以忽略)
旋转分析
简称
p :parent
g :grandfather
u :uncle
场景1
Cur 为红 , p 为 红 , g 为黑 , u 存在且为红色。
则将 p,u 改为 黑色,然后 g 改为红色,上溯。
场景2
Cur 为红 , p为红 , u 不存在/存在且为黑色 , g 为黑
这里 Cur 和 p 且为同一边, 当同为左时,右旋,同为右时,左旋。
分析
这里就需要分析了,这里存在俩种情况。
1. U不存在,那么pCur肯定为新增节点,如果Cur是上溯得到的结果的话,那Cur子树中必然有黑色节点,那么肯定在Cur没上溯变为红色前,这棵树一定就不平衡了。
2. U存在,现在要发生旋转,那pCur肯定不是新增节点,如果是新增节点,直接Cur变黑色即可,那么现在要发生旋转,必然是Cur的红色是上溯得到的结果。并且如果U存在,根据每条路径黑色节点数目相同的性质,C肯定为黑色。根据俩个节点不能同时为红色,那么a,b必然同为红色。
场景3
Cur为红色,p为红色,g为黑色,u为黑色或者不存在,此时 p / cur 不在一条边上,这个时候需要发生双旋转,如果cur 在 p的右边 , p在 g 左边的话,发生左右双旋转。那么Cur在p的左边,p在 g 的右边,发生右左双旋转。
这个图就不画了,根据上面那个图看就行了
分析
- U不存在,必然是新增节点,因为如果是上溯节点的话,g的右子树没有黑色节点,那么必然之前就不是平衡的,所以必定是新增节点。
- U存在,那么必然是上溯节点。而且P的另一边必为黑色。
#include <iostream>
#include <vector>
using namespace std;
enum COLOR
{
RED,
BALCK
};
template<class K,class V>
struct RBTreeNode
{
RBTreeNode()
:_key(0), _value(0), _Parent(NULL), _PLeft(NULL), _PRight(NULL), _color(RED)
{}
RBTreeNode(K key, V value,COLOR color=RED)
:_key(key), _value(value), _Parent(NULL), _PRight(NULL), _PLeft(NULL), _color(color)
{}
-K _key;
V _value;
RBTreeNode<K, V>*_Parent;
RBTreeNode<K, V> *_PRight;
RBTreeNode<K, V> * _PLeft;
COLOR _color;
};
template<class K, class V, class Ref, class Pointer>
class RBTreeIterator
{
typedef RBTreeNode<K, V> Node;
typedef RBTreeIterator<K, V, Ref, Pointer> Self;
public:
RBTreeIterator()
: _pNode(NULL)
{}
RBTreeIterator(Node* pNode)
: _pNode(pNode)
{}
RBTreeIterator(RBTreeIterator& it)
: _pNode(it._pNode)
{}
Self& operator++()
{
_Increment();
return *this;
}
Self operator++(int)
{
Node*temp = _pNode;
_Increment();
return RBTreeIterator(temp);
}
Self& operator--()
{
_Decrement();
}
Self operator--(int)
{
Node*temp = _pNode;
_Increment()
return RBTreeIterator(temp);
}
Ref operator*()
{
return _pNode->_key;
}
const Ref operator*()const
{
return _pNode->_key;
}
Pointer operator->()
{
return &(_pNode->_key);
}
const Pointer operator->()const
{
return &(_pNode->_key);
}
bool operator==(const Self& it)
{
return _pNode == it._pNode;
}
bool operator!=(const Self& it)
{
return _pNode != it._pNode;
}
protected:
void _Increment()
{
if (_pNode)
{
Node*pCur = _pNode;
if (pCur->_Parent == pCur&&pCur->_color == RED) return ; //处理End
if (pCur->_PRight)
{
pCur = pCur->_PRight;
while (pCur->_PLeft) pCur = pCur->_PLeft;
}
else
{
Node*parent = pCur->_Parent;
while (parent->_PRight == pCur)
{
pCur = pCur->_Parent;
parent = parent->_Parent;
}
if (pCur->_PRight != parent)pCur = pCur->_Parent; //处理当根为最大时,这里pCur为End,为了不让它走回去设置了这一条件
}
_pNode = pCur;
}
}
void _Decrement()
{
if (_pNode)
{
Node * pCur = _pNode;
if (pCur->_PLeft)
{
pCur = pCur->_PLeft;
while (pCur->_PRight)
{
pCur = pCur->_PRight;
}
}
else
{
Node*parent = pCur->_Parent;
if (parent->_PLeft == pCur)
{
pCur = pCur->_Parent;
parent = parent->_Parent;
}
pCur = pCur->_Parent; // 这里不加,是为了让 根为最小时当走到End,在走回最小节点
}
_PNode = pCur;
}
}
protected:
Node* _pNode;
};
template<class K,class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
typedef RBTreeIterator<K, V, K&, K*> Iterator;
public:
RBTree(V arr[], size_t size)
:_pHead(new RBTreeNode<K,V>())
{
for (size_t idx = 0; idx < size; ++idx)
{
_Insert(arr[idx], idx);
}
_pHead->_PLeft = Min();
_pHead->_PRight = Max();
}
void InOrder()
{
cout << "InOrder: ";
_InOrder(_GetRoot());
cout << endl;
}
bool CheckRBTree()
{
Node*_Root = _pHead->_Parent;
if (_Root == NULL||(_Root->_PLeft==NULL&&_Root->_PRight==NULL&&_Root->_color==BALCK)) return true;
else
{
size_t k = 0;
Node*pCur = _Root;
while (pCur->_PLeft)
{
if (pCur->_color == BALCK) k++;
if (pCur->_color == RED&&(pCur->_PLeft->_color==pCur->_color)) return false; // 先找一条路径上的黑色节点的数目
pCur = pCur->_PLeft;
}
if (pCur->_color == BALCK) k++;
return _CheckRBTree(_Root, 1, k); //这个传1的原因是从跟节点开始,根的数目为1,也为了防止只有根节点的情况出现,只有根节点的话,这里对比的参照变量肯定为1,这里传0的话肯定是错的。
}
}
Iterator Begin()
{
return _pHead->_PLeft;
}
Iterator End()
{
return _pHead;
}
bool Empty()const
{
return Begin() == End();
}
size_t Size()const
{
return _size;
}
protected:
Node* &_GetRoot()
{
return _pHead->_Parent;
}
bool _CheckRBTree(Node* pRoot, size_t blackCoount, const size_t k)
{
bool flag = false, flag_2 = false;
if (pRoot)
{
if (pRoot->_PLeft == NULL&&pRoot->_PRight == NULL)
{
if (k == blackCoount)
return true;
else
return false;
}
if (pRoot->_PLeft)
{
if (pRoot->_PLeft->_color == BALCK)
blackCoount++;
else if(pRoot->_PLeft->_color==pRoot->_color)
return false;
flag=_CheckRBTree(pRoot->_pLeft, blackCoount, k);
}
if (pRoot->_PRight)
{
if (pRoot->_PRight->_color == BALCK)
blackCoount++;
else if(pRoot->_PRight->_color==pRoot->_color)
return false;
flag_2=_CheckRBTree(pRoot->_PRight, blackCoount, k);
}
return flag&&flag_2;
}
else
{
return true;
}
}
void _InOrder(Node* pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_PLeft);
cout << pRoot->_key << " ";
_InOrder(pRoot->_PRight);
}
}
void _RotateL(Node*parent)
{
Node*_Root = _pHead->_Parent;
Node * PSubR = parent->_PRight;
Node * PSubRL = PSubR->_PLeft;
Node * Pparent = parent->_Parent;
if (PSubRL)
{
PSubRL->_Parent = parent;
}
parent->_PRight = PSubRL;
parent->_Parent = PSubR;
PSubR->_PLeft = parent;
PSubR->_Parent = Pparent;
if (Pparent == _pHead)
{
_pHead->_Parent = PSubR;
}
else
{
if (Pparent->_PLeft == parent)Pparent->_PLeft = PSubR;
else Pparent->_PRight = PSubR;
}
}
void _RotateR(Node*parent)
{
Node*_Root = _pHead->_Parent;
Node*PSubL = parent->_PLeft;
Node*PSubLR = PSubL->_PRight;
Node*Pparent = parent->_Parent;
if (PSubLR)
{
PSubLR->_Parent = parent;
}
parent->_PLeft = PSubLR;
parent->_Parent = PSubL;
PSubL->_PRight = parent;
PSubL->_Parent = Pparent;
if (Pparent == _pHead)
{
_pHead->_Parent = PSubL;
}
else
{
if (Pparent->_PLeft == parent)Pparent->_PLeft = PSubL;
else Pparent->_PRight = PSubL;
}
}
bool _Insert(K key, V value)
{
Node * _Root = _pHead->_Parent;
if (NULL==_Root)
{
_Root = new Node(key, value);
_Root->_color = BALCK;
_Root->_Parent = _pHead;
_pHead->_Parent = _Root;
_pHead->_PLeft = _Root;
_pHead->_PRight = _Root;
_size++;
return true;
}
else
{
Node*pCur = _Root;
Node*Parent = NULL;
while (pCur)
{
if (key < pCur->_key)
{
Parent = pCur;
pCur = pCur->_PLeft;
}
else if (key>pCur->_key)
{
Parent = pCur;
pCur = pCur->_PRight;
}
else
{
return false;
}
}
pCur = new Node(key, value);
if (key < Parent->_key)
{
Parent->_PLeft = pCur;
pCur->_Parent = Parent;
}
else
{
Parent->_PRight = pCur;
pCur->_Parent = Parent;
}
if (Parent->_color == BALCK)
{
_size++;
return true;
}
else
{
Node* grandfather = NULL;
Node* uncle = NULL;
while (_Root != Parent&& Parent != _pHead) // 原来 _Root != Parent&& Parent != NULL ,现在加入了_pHead 把判断为空的地方换成pHead即可
{
grandfather = Parent->_Parent;
if (grandfather->_PLeft == Parent) uncle = grandfather->_PRight;
else uncle = grandfather->_PLeft;
if (uncle&&uncle->_color == RED)
{
uncle->_color = BALCK;
Parent->_color = BALCK;
grandfather->_color = RED;
pCur = grandfather;
Parent = grandfather->_Parent;
}
else if (Parent==grandfather->_PLeft)
{
if (pCur == Parent->_PRight)
{
_RotateL(Parent);
swap(Parent, pCur);
}
_RotateR(grandfather);
Parent->_color= BALCK;
grandfather->_color = RED;
_size++;
return true;
}
else if (Parent == grandfather->_PRight)
{
if (pCur == Parent->_PLeft)
{
_RotateR(Parent);
swap(Parent, pCur);
}
_RotateL(grandfather);
Parent ->_color= BALCK;
grandfather->_color = RED;
_size++;
return true;
}
}
_Root->_color = BALCK;
_size++;
return true;
}
}
}
Node *Min()
{
Node*_Root = _pHead->_Parent;
Node*pCur = _Root;
if (pCur)
{
while (pCur->_PLeft) pCur = pCur->_PLeft;
return pCur;
}
else return NULL;
}
Node *Max()
{
Node*_Root = _pHead->_Parent;
Node*pCur = _Root;
if (pCur)
{
while (pCur->_PRight) pCur = pCur->_PRight;
return pCur;
}
else return NULL;
}
private:
//Node * _Root;
Node * _pHead;
size_t _size;
};
void TestRBTree()
{
int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
RBTree<int, int> t(a,sizeof(a)/sizeof(a[0]));
t.InOrder();
if (t.CheckRBTree())
{
cout << "是红黑树" << endl;
}
else
{
cout << "不是红黑树" << endl;
}
}
判断红黑树是否平衡
bool CheckRBTree()
{
Node*_Root = _pHead->_Parent;
if (_Root == NULL||(_Root->_PLeft==NULL&&_Root->_PRight==NULL&&_Root->_color==BALCK)) return true;
else
{
size_t k = 0;
Node*pCur = _Root;
while (pCur->_PLeft)
{
if (pCur->_color == BALCK) k++;
if (pCur->_color == RED&&(pCur->_PLeft->_color==pCur->_color)) return false; // 先找一条路径上的黑色节点的数目
pCur = pCur->_PLeft;
}
if (pCur->_color == BALCK) k++;
return _CheckRBTree(_Root, 1, k); //这个传1的原因是从跟节点开始,根的数目为1,也为了防止只有根节点的情况出现,只有根节点的话,这里对比的参照变量肯定为1,这里传0的话肯定是错的。
}
}
bool _CheckRBTree(Node* pRoot, size_t blackCoount, const size_t k)
{
bool flag = false, flag_2 = false;
if (pRoot)
{
if (pRoot->_PLeft == NULL&&pRoot->_PRight == NULL)
{
if (k == blackCoount)
return true;
else
return false;
}
if (pRoot->_PLeft)
{
if (pRoot->_PLeft->_color == BALCK)
blackCoount++;
else if(pRoot->_PLeft->_color==pRoot->_color)
return false;
flag=_CheckRBTree(pRoot->_pLeft, blackCoount, k);
}
if (pRoot->_PRight)
{
if (pRoot->_PRight->_color == BALCK)
blackCoount++;
else if(pRoot->_PRight->_color==pRoot->_color)
return false;
flag_2=_CheckRBTree(pRoot->_PRight, blackCoount, k);
}
return flag&&flag_2;
}
else
{
return true;
}
}
map
set与map就是使用红黑树进行了封装,map的value是pair < key,value> ,它的key 使用了仿函数KeyofValue返回得到的key,红黑树只保存了map的value也就是pair键值对
说起来pair键值对,有俩个构造方法,第一个是make_pair,第二个是pair< T1,T2> (t1,t2)直接用pair构造函数来生成。但是它们俩个当中pair直接构造的方式的效率更高。从下面的代码中看到 make_pair比正常直接使用pair构造函数多了一次拷贝构造。
1 // TEMPLATE STRUCT pair
2 template<class _Ty1,class _Ty2> struct pair
3 { // store a pair of values
4 typedef pair<_Ty1, _Ty2> _Myt;
5 typedef _Ty1 first_type;
6 typedef _Ty2 second_type;
7
8 pair(): first(_Ty1()), second(_Ty2())
9 { // construct from defaults
10 }
11
12 pair(const _Ty1& _Val1, const _Ty2& _Val2): first(_Val1), second(_Val2)
13 { // construct from specified values
14 }
15
16 template<class _Other1,
17 class _Other2>
18 pair(const pair<_Other1, _Other2>& _Right)
19 : first(_Right.first), second(_Right.second)
20 { // construct from compatible pair
21 }
22
23 void swap(_Myt& _Right)
24 { // exchange contents with _Right
25 std::swap(first, _Right.first);
26 std::swap(second, _Right.second);
27 }
28
29 _Ty1 first; // the first stored value
30 _Ty2 second; // the second stored value
31 };
32
33
34 template<class _Ty1,class _Ty2> inline
35 pair<_Ty1, _Ty2> make_pair(_Ty1 _Val1, _Ty2 _Val2)
36 { // return pair composed from arguments
37 return (pair<_Ty1, _Ty2>(_Val1, _Val2));
38 }