1.紅黑樹的概念:紅黑樹是一棵二叉搜索樹,它在每個節點上增加一個存儲位來表示節點的顏色,可以是red或black,通過對任何一條從根節點到葉子節點上的間單路徑來約束,紅黑樹保證最長路徑不超過最短路徑的兩倍,因而近視平衡。
2.紅黑樹的性質
- 性質1,每個節點不是黑色就是紅色
- 性質2,根節點是黑色的;
- 性質3,如果一個根節點是紅色的,則它的兩個葉子節點是紅色的,即沒有兩個連續節點是紅色節點
- 性質4,對於每一個節點,從該節點到其所有後代葉節點的簡單路徑上,均包含相同數目的黑色節點,即每條路徑上黑色節點的個數是相等的;
- 性質5,每個節點其空指針域是顏色的黑色的
滿足上訴性質的二叉搜索樹是二叉搜索樹
3.具體插入節點的步驟:
對於插入節點的雙親節點是紅色時,我們又分爲三種情況對其調整
情況1
情況2
- 情況3
4.根據上述的五種情況,實現代碼
#include<stdio.h>
#include<iostream>
using namespace std;
enum COLOR{RED,BLACK,};
template<class k,class v>
struct RBTreeNode
{
RBTreeNode(const k& key,const v& value,COLOR color = RED)
:_pLeft(NULL)
,_pRight(NULL)
,_pParent(NULL)
,_key(key)
,_value(value)
,_color(color)
{}
RBTreeNode<k,v>* _pLeft;
RBTreeNode<k,v>* _pRight;
RBTreeNode<k,v>* _pParent;
k _key;
v _value;
COLOR _color;
};
template<class k,class v>
class RBTree
{
public:
typedef RBTreeNode<k,v> Node;
RBTree()
:_pRoot(NULL)
{}
bool Insert(const k& key,const v& value)
{
return _Insert(key,value);
}
void InOrder()
{
cout<<"InOrder: ";
_InOrder(_pRoot);
cout<<endl;
}
bool CheckRBTree()
{
if(_pRoot == NULL)
return true;
if(_pRoot->_pLeft == NULL && _pRoot->_pRight == NULL)
{
if(_pRoot->_color == BLACK)
return true;
else
return false;
}
int blackcount = 0;
Node* pCur = _pRoot;
while(pCur)
{
if(pCur->_color == BLACK)
blackcount++;
pCur= pCur->_pLeft;
}
int k = 0;
return _CheckRBTree(_pRoot,blackcount,k);
}
private:
bool _CheckRBTree(Node* pRoot,int blackcount,int k)
{
if(pRoot == NULL)
return true;
if(pRoot->_color == BLACK)
++k;
Node* pParent = pRoot->_pParent;
if(pParent && pParent->_color == RED && pRoot->_color == RED)
{
cout<<"紅色節點相鄰,違反了性質3"<<endl;
return false;
}
if(pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
{
if(k != blackcount)
{
cout<<"每條路徑的黑色節點個數不同,違反了性質4"<<endl;
return false;
}
}
return _CheckRBTree(pRoot->_pLeft,blackcount,k)&&_CheckRBTree(pRoot->_pRight,blackcount,k);
}
void _InOrder(Node* pRoot)
{
if(pRoot == NULL)
return;
_InOrder(pRoot->_pLeft);
cout<<pRoot->_key<<" ";
_InOrder(pRoot->_pRight);
}
bool _Insert(const k& key,const v& value)
{
if(_pRoot == NULL)
{
_pRoot = new Node(key,value,BLACK);
return true;
}
//找到要節點刪除的位置
Node* pNode = _pRoot;
Node* pParent = NULL;
while(pNode)
{
if(pNode->_key > key)
{
pParent = pNode;
pNode = pNode->_pLeft;
}
else if(pNode->_key < key)
{
pParent = pNode;
pNode = pNode->_pRight;
}
else
{
return false;//找到key值節點,不用插入,直接退出
}
}
//已經找到
pNode = new Node(key,value);
if(pParent->_key > key)
{
pParent->_pLeft = pNode;
pNode->_pParent = pParent;
}
else
{
pParent->_pRight = pNode;
pNode->_pParent = pParent;
}
//對紅黑樹進行調整
while(pParent && pParent->_color == RED && pNode->_color == RED)
{
Node* grandFather = pParent->_pParent;
Node* pUncle = NULL;
////找到pUncle節點
//if(grandFather->_pLeft == pParent)
// pUncle = grandFather->_pRight;
//else
// pUncle = grandFather->_pLeft;
if(grandFather->_pLeft == pParent)//節點插在左子樹
{
pUncle = grandFather->_pRight;
if(pUncle && pUncle->_color == RED)//情況一
{
pUncle->_color = BLACK;
pParent->_color = BLACK;
grandFather->_color = RED;
pNode = grandFather;
pParent = grandFather->_pParent;
}
else//在處理情況三的過程中順便處理情況二
{
if(pParent && pParent->_pRight == pNode)
{
//先左旋再右旋
_RotateL(pParent);
swap(pNode,pParent);
}
grandFather->_color = RED;
pParent->_color = BLACK;
_RotateR(grandFather);
}
}
else
{
pUncle = grandFather->_pLeft;
if(pUncle && pUncle->_color == RED)//情況一
{
pUncle->_color = BLACK;
pParent->_color = BLACK;
grandFather->_color = RED;
pNode = grandFather;
pParent = grandFather->_pParent;
}
//在處理情況三的過程中順便處理情況二
else
{
if(pUncle && pUncle->_color == BLACK && pParent->_pLeft == pNode)//情況三
{
//先左旋再右旋
_RotateR(pParent);
swap(pNode,pParent);
}
grandFather->_color = RED;//情況二
pParent->_color = BLACK;
_RotateL(grandFather);
}
}
}
_pRoot->_color = BLACK;
}
void _RotateL(Node*& pParent)
{
Node* pSubR = pParent->_pRight;
Node* pSubRL = pSubR->_pLeft;
pParent->_pRight = pSubRL;
if(pSubRL)
pSubRL->_pParent = pParent;
pSubR->_pLeft = pParent;
Node* pPParent = pParent->_pParent;
pParent->_pParent = pSubR;
pSubR->_pParent = pPParent;
if(pPParent == NULL)
_pRoot = pSubR;
else if(pPParent->_pLeft == pParent)
pPParent->_pLeft = pSubR;
else
pPParent->_pRight = pSubR;
}
void _RotateR(Node*& pParent)
{
Node* pSubL = pParent->_pLeft;
Node* pSubLR = pSubL->_pRight;
pParent->_pLeft = pSubLR;
if(pSubLR)
pSubLR->_pParent = pParent;
pSubL->_pRight = pParent;
Node* pPParent = pParent->_pParent;
pParent->_pParent = pSubL;
pSubL->_pParent = pPParent;
if(pPParent==NULL)
_pRoot = pSubL;
else if(pPParent->_pLeft == pParent)
pPParent->_pLeft = pSubL;
else
pPParent->_pRight = pSubL;
}
private:
Node* _pRoot;
};
測試代碼:
void funtest()
{
RBTree<int ,int> rbt;
int array[] = {40,30,60,10,50,80,20,70};
for(size_t idx=0; idx<sizeof(array)/sizeof(array[0]); ++idx)
rbt.Insert(array[idx],array[idx]);
rbt.InOrder();
if(rbt.CheckRBTree())
{
cout<<"該樹是紅黑樹"<<endl;
}
else
{
cout<<"該樹不是紅黑樹"<<endl;
}
}
int main()
{
funtest();
getchar();
return 0;
}