在說紅黑樹之前,我們先來認識一下它:
首先強調一點:紅黑樹也是二叉搜索樹。那麼它就滿足二叉搜索樹的性質,除此之外,他還有幾個比較特殊的性質,瞭解這些,有助於我們後面的分析
性質:
1、紅黑樹所有的節點都有顏色(紅或黑)
2、紅黑樹的根結點是黑色的
3、紅黑樹的兩個紅色節點不能相連
4、紅黑樹的每一條鏈的黑節點的個數相同
5、所有空的節點都是黑色的
知道了這些之後開始進入紅黑樹的創建:
顯然這就是紅黑樹的插入操作的編寫了,那麼要想將一個節點插入紅黑樹中,首先你得判斷紅黑樹是不是空的,如果是空的,那麼直接就可以插入;不是空的,那麼得找插入位置,然後再插入,這一點和二叉搜索樹的插入是一樣的。不過需要注意,最後把根結點置成黑色的
但是之後呢?
插入的節點我們都默認爲紅色的,但是性質3說,紅色的節點不能相鏈,如果,之後我們不管的話,性質3肯定不會滿足的,所以我們需要對紅黑樹進行調解,讓其滿足這些性質。那麼我們就需要分情況討論了,我們重點分析一下,兩個紅色節點相鏈的情況怎麼處理。
總共可以分爲3種情況:
情況一:
雙親結點爲紅色,祖先結點爲黑色, 叔叔節點存在,且爲紅色
其實這個圖裏包含了四種情況,我只是將其中的一種情況中的轉化後的形式畫了出來,其他的也一樣。
情況二:
雙親結點爲紅色,祖先結點爲黑色,叔叔節點不存在或存在爲黑色
這種情況是:雙親在祖先節點的左的同時pCur在雙親的左;或是雙親在祖先節點的右的同時,pCur在雙親的右。
這樣我們就可以進行單旋處理,根據情況調用左單旋還是右單旋。
情況三:
雙親結點爲紅色,祖先結點爲黑色,叔叔節點不存在或存在爲黑色
這個和情況二是互補的,情況二中剩下的都是不能單旋直接處理的,那麼就需要雙旋,圖中畫的是左右雙旋,先左旋之後,我們發現,和情況二的一樣,那麼代碼中這一塊就可以放在一起處理。
不過,這裏需要注意一點,就是,左旋之後只想pCur變成了雙親,而parent變成了孩子,所以,在第一次旋轉之後先對這兩個指針進行交換,在進行第二次旋轉。
最後將插入寫完之後,我們可以寫一個函數來測試一下這個是不是紅黑樹,這個其實也是對紅黑樹的性質的檢驗。其中重點驗證性質3和性質4。那麼我們來分析一下這步驟:
1、判斷這個樹是不是空樹,是的話,直接返回true
2、驗證性質2,判斷根結點的顏色是不是黑色的,是,返回true
3、要驗證性質三,得遍歷整個樹,而性質4的驗證也要這莫做,那麼我們將這兩個一起驗證。那麼首先我們得求出一條鏈的黑色節點的個數,並將其保存起來,再遞歸遍歷左右子樹,驗證。
//無迭代器
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
RBTree()
:_pRoot(NULL)
{}
// 首先:搜索樹
bool Insert(const K& key, const V& value)
{
if (_pRoot == NULL)
{
_pRoot = new Node(key, value);
_pRoot->_color = BLACK;
return true;
}
//找插入位置
Node*pCur = _pRoot;
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;
else
parent->_pRight = pCur;
pCur->_pParent = parent;//注意,不要遺漏了。。。
//看紅黑樹是否還滿足其性質(分情況討論)
while (_pRoot!=pCur && pCur->_pParent->_color == RED)
{
Node* gf = parent->_pParent;//保存雙親的雙親
//gf肯定存在,因爲,如果不存在,那麼parent就是根結點,是黑色的,不會進入這個循環
//雙親在左,叔叔(存在的話)在右
if (gf->_pLeft == parent)
{
Node*uncle = gf->_pRight;
if (uncle && uncle->_color == RED) //情況一
{
parent->_color = BLACK;
uncle->_color = BLACK;
gf->_color = RED;
//向上更新
pCur = gf;
parent = pCur->_pParent;
}
else //情況二、三(將情況三轉化爲情況二,再一起處理)
{
if (parent->_pRight == pCur)
{
_RotateL(parent);
std::swap(parent, pCur);
}
gf->_color = RED;
parent->_color = BLACK;
_RotateR(gf);
}
}
else//雙親在右
{
Node*uncle = gf->_pLeft;
if (uncle && uncle->_color == RED) //情況一
{
parent->_color = BLACK;
uncle->_color = BLACK;
gf->_color = RED;
//向上更新
pCur = gf;
parent = pCur->_pParent;
}
else //情況二、三(將情況三轉化爲情況二,再一起處理)
{
if (parent->_pLeft == pCur)
{
_RotateR(parent);
std::swap(parent, pCur);
}
gf->_color = RED;
parent->_color = BLACK;
_RotateL(gf);
}
}
}
_pRoot->_color = BLACK;
return true;
}
void InOrder()
{
cout << "InOrder: ";
_InOrder(_pRoot);
cout << endl;
}
//判斷是不是紅黑樹
bool CheckRBTree()
{
if (_pRoot == NULL)
return true;
if (_pRoot->_color == RED)//違反性質2“根結點爲黑色”
return false;
size_t blackcount = 0;//統計一條鏈中黑色結點的數量
Node* pCur = _pRoot;
while (pCur)
{
if (pCur->_color == BLACK)
blackcount++;
pCur = pCur->_pLeft;//這裏以最左邊的那一條鏈爲例
}
//驗證性質4“每條鏈上的黑色結點都相等”,順便驗證性質3“紅色結點不能相連”
return _CheckRBTree(_pRoot, blackcount, 0);
}
private:
//判斷是不是紅黑樹(遞歸)
//k用來統計每一條鏈上的黑色結點的個數,但是不能給成引用,否則,再次統計下一條鏈的時候,就不會更新
bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k)
{
if (pRoot == NULL)
return true;
if (pRoot->_color == BLACK)
k++;
Node* parent = pRoot->_pParent;
if (parent && parent->_color == RED && pRoot->_color == RED)//違反性質3
return false;
if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL)
{
if (k != blackCount)//違反性質4
return false;
}
return _CheckRBTree(pRoot->_pLeft, blackCount, k)
&& _CheckRBTree(pRoot->_pRight, blackCount, k);
}
//左旋
void _RotateL(Node* parent)
{
Node* subR = parent->_pRight;
Node* subRL = subR->_pLeft;//有可能不存在
parent->_pRight = subRL;
if (subRL)
subRL->_pParent = parent;
subR->_pLeft = parent;
Node* gparent = parent->_pParent;//保存parent的雙親
parent->_pParent = subR;
if (gparent == NULL)//parent是根結點
_pRoot = subR;
else if (gparent->_pLeft == parent)
gparent->_pLeft = subR;
else
gparent->_pRight = subR;
subR->_pParent = gparent;//第三個
}
//右旋
void _RotateR(Node* parent)
{
Node*subL = parent->_pLeft;
Node*subLR = subL->_pRight;
parent->_pLeft = subLR;
if (subLR)
subL->_pParent = parent;
subL->_pRight = parent;
Node*gparent = parent->_pParent;
parent->_pParent = subL;
subL->_pParent = gparent;
if (gparent == NULL)
_pRoot = subL;
else if (gparent->_pLeft == parent)
gparent->_pLeft = subL;
else
gparent->_pRight = subL;
}
//中序遍歷
void _InOrder(Node* pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_pLeft);
cout << pRoot->_key << " ";
_InOrder(pRoot->_pRight);
}
}
//獲取最小節點
Node* _GetMinNode()
{
Node* pCur = _pRoot;
Node*parent = NULL;
while (pCur)
{
parent = pCur;
pCur = pCur->_pLeft;
}
return parent;
}
//獲取最大節點
Node* _GetMaxNode()
{
Node* pCur = _pRoot;
Node*parent = NULL;
while (pCur)
{
parent = pCur;
pCur = pCur->_pRight;
}
return parent;
}
private:
Node* _pRoot;
};
#endif
void TestRBTree()
{
int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
RBTree<int, int> t;
for (int idx = 0; idx < sizeof(a) / sizeof(a[0]); ++idx)
t.Insert(a[idx], idx);
t.InOrder();
if (t.CheckRBTree())
{
cout << "是紅黑樹" << endl;
}
else
{
cout << "不是紅黑樹" << endl;
}
}
迭代器中給出了什麼操作:
Self& operator++();
Self operator++(int);
Self& operator--();
Self operator--(int);
Ref operator*();//這裏的Ref是我自己通過模板類給出的類型
const Ref operator*()const ;
Pointer operator->();
const Pointer operator->()const;
這裏重點就是自增和自減的操作,我們知道紅黑是是二叉搜索樹,那麼他的中序遍歷是有序的,所以,在迭代器下,一個節點的下一個節點是它右子樹的最左邊的節點;同樣,一個節點的上一個節點是他左子樹的最右邊的節點。
但是這裏總有一些例外的情況,如:一個結點右子樹沒有左節點那麼怎麼處理,或是左子樹沒有右節點呢?
對於這兩種情況我們需要特別處理,那麼以第二個圖來說,這是右子樹沒有左節點的情況,也就是自增的情況,那麼我們需要將其雙親保存起來,然後向上面遍歷們直到找到一個其左孩子存在爲止,這時候,其就是要找的節點。
同樣的,自減也是這樣,不過這裏需要要遭注意一個特殊的地方,就是,在頭結點的位置,我們要是進行自減的話,按理說,應該是到key最大的位置,但是,我們的代碼中,並不適用這個,所以,我們需要拿出來單獨處理。
void _Increment()
{
//找右子樹的最左邊的節點
if (_pNode->_pRight)
{
_pNode = _pNode->_pRight;
while (_pNode->_pLeft)
_pNode = _pNode->_pLeft;
}
//特殊情況
else
{
Node* parent = _pNode->_pParent;
while (parent->_pRight == _pNode)
{
_pNode = parent;
parent = parent->_pParent;
}
if (parent->_pRight != _pNode)
_pNode = parent;
}
}
void _Decrement()
{
//頭結點的情況:自減之後到key最大的結點
if (_pNode->_color == RED&&_pNode->_pParent->_pParent == _pNode)
_pNode = _pNode->_pRight;
//找左子樹的最右邊的節點
else if (_pNode->_pLeft)
{
_pNode = _pNode->_pLeft;
while (_pNode->_pRight)
_pNode = _pNode->_pRight;
}
//特殊情況處理
else
{
Node* parent = _pNode->_pParent;
while (parent->_pLeft == _pNode)
{
_pNode = parent;
parent = parent->_pParent;
}
_pNode = parent;
}
}
下面是完整的代碼:
#include<iostream>
using namespace std;
enum COLOR{ RED, BLACK };
template<class K, class V>
struct RBTreeNode
{
RBTreeNode(const K& key = K(), const V& value = V(), const 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; //結點的顏色,初始值爲紅色
};
#if 0
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)
{
Self temp = *this;
_Increment();
return temp;
}
Self& operator--()
{
_Decrement();
return *this;
}
Self operator--(int)
{
Self temp = *this;
_Decrement();
return temp;
}
Ref operator*()
{
return _pNode->_key;
}
const Ref operator*()const
{
return _pNode->_key;
}
Pointer operator->()
{
return &(operator*());
}
const Pointer operator->()const
{
return &(operator*());
}
bool operator==(const Self& it)
{
return _pNode == it._pNode;
}
bool operator!=(const Self& it)
{
return _pNode != it._pNode;
}
protected:
void _Increment()
{
//找右子樹的最左邊的節點
if (_pNode->_pRight)
{
_pNode = _pNode->_pRight;
while (_pNode->_pLeft)
_pNode = _pNode->_pLeft;
}
//特殊情況
else
{
Node* parent = _pNode->_pParent;
while (parent->_pRight == _pNode)
{
_pNode = parent;
parent = parent->_pParent;
}
if (parent->_pRight != _pNode)
_pNode = parent;
}
}
void _Decrement()
{
//頭結點的情況:自減之後到key最大的結點
if (_pNode->_color == RED&&_pNode->_pParent->_pParent == _pNode)
_pNode = _pNode->_pRight;
//找左子樹的最右邊的節點
else if (_pNode->_pLeft)
{
_pNode = _pNode->_pLeft;
while (_pNode->_pRight)
_pNode = _pNode->_pRight;
}
//特殊情況處理
else
{
Node* parent = _pNode->_pParent;
while (parent->_pLeft == _pNode)
{
_pNode = parent;
parent = parent->_pParent;
}
_pNode = parent;
}
}
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()
:_size(0)
{
_pHead = new Node(K(), V());
_pHead->_pLeft = _pHead;
_pHead->_pRight = _pHead;
_pHead->_pParent = NULL;
_pHead->_color = RED;
}
Iterator Begin()
{
return Iterator(_pHead->_pLeft);
}
Iterator End()
{
return Iterator(_pHead);//注意end的位置,不是最大的key所在結點
}
bool Empty()const
{
return _size == 0;
}
size_t Size()const
{
return _size;
}
Iterator Find(const K& key)
{
Iterator it = Begin();
while (it != End())
{
if (key == *it)
return it;
else
++it;
}
}
// 首先:搜索樹
bool Insert(const K& key, const V& value)
{
Node* pRoot = _GetRoot();
if (pRoot == NULL)
{
Node* pRoot = new Node(key, value);
pRoot->_pParent = _pHead;
_pHead->_pParent = pRoot;
pRoot->_color = BLACK;
_size++;
return true;
}
//找插入位置
Node*pCur = pRoot;
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;
else
parent->_pRight = pCur;
_size++;
pCur->_pParent = parent;//注意,不要遺漏了。。。
//看紅黑樹是否還滿足其性質(分情況討論)
while (pRoot != pCur && parent->_color == RED)//這個條件很重要
{
Node* gf = parent->_pParent;//保存雙親的雙親
//雙親在左,叔叔(存在的話)在右
if (gf->_pLeft == parent)
{
Node*uncle = gf->_pRight;
if (uncle && uncle->_color == RED) //情況一
{
parent->_color = BLACK;
uncle->_color = BLACK;
gf->_color = RED;
//向上更新
pCur = gf;
parent = pCur->_pParent;
}
else //情況二、三(將情況三轉化爲情況二,再一起處理)
{
if (parent->_pRight == pCur)
{
_RotateL(parent);
std::swap(parent, pCur);
}
gf->_color = RED;
parent->_color = BLACK;
_RotateR(gf);
}
}
else//雙親在右
{
Node*uncle = gf->_pLeft;
if (uncle && uncle->_color == RED) //情況一
{
parent->_color = BLACK;
uncle->_color = BLACK;
gf->_color = RED;
//向上更新
pCur = gf;
parent = pCur->_pParent;
}
else //情況二、三(將情況三轉化爲情況二,再一起處理)
{
if (parent->_pLeft == pCur)
{
_RotateR(parent);
std::swap(parent, pCur);
}
gf->_color = RED;
parent->_color = BLACK;
_RotateL(gf);
}
}
}
pRoot = _GetRoot();//旋轉完成之後要再把根結點獲取一遍
pRoot->_color = BLACK;
_pHead->_pLeft = _GetMinNode();
_pHead->_pRight = _GetMaxNode();
return true;
}
void InOrder()
{
cout << "InOrder: ";
_InOrder(_GetRoot());
cout << endl;
}
//判斷是不是紅黑樹
bool CheckRBTree()
{
Node* pRoot = _GetRoot();
if (pRoot == NULL)
return true;
if (pRoot->_color == RED)//違反性質2“根結點爲黑色”
return false;
size_t blackcount = 0;//統計一條鏈中黑色結點的數量
while (pRoot)
{
if (pRoot->_color == BLACK)
blackcount++;
pRoot = pRoot->_pLeft;//這裏以最左邊的那一條鏈爲例
}
//驗證性質4“每條鏈上的黑色結點都相等”,順便驗證性質3“紅色結點不能相連”
return _CheckRBTree(pRoot, blackcount, 0);
}
private:
//判斷是不是紅黑樹(遞歸)
//k用來統計每一條鏈上的黑色結點的個數,但是不能給成引用,否則,再次統計下一條鏈的時候,就不會更新
bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k)
{
if (pRoot == NULL)
return true;
if (pRoot->_color == BLACK)
k++;
Node* parent = pRoot->_pParent;
if (parent && parent->_color == RED && pRoot->_color == RED)//違反性質3
return false;
if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL)
{
if (k != blackCount)//違反性質4
return false;
}
return _CheckRBTree(pRoot->_pLeft, blackCount, k)
&& _CheckRBTree(pRoot->_pRight, blackCount, k);
}
//左旋
void _RotateL(Node* parent)
{
Node* subR = parent->_pRight;
Node* subRL = subR->_pLeft;//有可能不存在
parent->_pRight = subRL;
if (subRL)
subRL->_pParent = parent;
subR->_pLeft = parent;
Node* gparent = parent->_pParent;//保存parent的雙親
parent->_pParent = subR;
if (gparent == _pHead)//parent是根結點
{
_pHead->_pParent = subR; //注意:這一塊的根結點怎麼表示
subR->_pParent = _pHead;
}
else if (gparent->_pLeft == parent)
gparent->_pLeft = subR;
else
gparent->_pRight = subR;
subR->_pParent = gparent;//第三個
}
//右旋
void _RotateR(Node* parent)
{
Node*subL = parent->_pLeft;
Node*subLR = subL->_pRight;
parent->_pLeft = subLR;
if (subLR)
subL->_pParent = parent;
subL->_pRight = parent;
Node*gparent = parent->_pParent;
parent->_pParent = subL;
subL->_pParent = gparent;
if (gparent == _pHead)
{
_pHead->_pParent = subL;
subL->_pParent = _pHead;
}
else if (gparent->_pLeft == parent)
gparent->_pLeft = subL;
else
gparent->_pRight = subL;
}
//中序遍歷
void _InOrder(Node* pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_pLeft);
cout << pRoot->_key << " ";
_InOrder(pRoot->_pRight);
}
}
//獲取根結點
Node* &_GetRoot()
{
return _pHead->_pParent;
}
//獲取最小節點
Node* _GetMinNode()
{
Node*pRoot = _pHead->_pParent;
Node*parent = NULL;
while (pRoot)
{
parent = pRoot;
pRoot = pRoot->_pLeft;
}
return parent;
}
//獲取最大節點
Node* _GetMaxNode()
{
Node*pRoot = _pHead->_pParent;
Node*parent = NULL;
while (pRoot)
{
parent = pRoot;
pRoot = pRoot->_pRight;
}
return parent;
}
private:
Node* _pHead; //頭結點
size_t _size;
};
#else
//無迭代器
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
RBTree()
:_pRoot(NULL)
{}
// 首先:搜索樹
bool Insert(const K& key, const V& value)
{
if (_pRoot == NULL)
{
_pRoot = new Node(key, value);
_pRoot->_color = BLACK;
return true;
}
//找插入位置
Node*pCur = _pRoot;
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;
else
parent->_pRight = pCur;
pCur->_pParent = parent;//注意,不要遺漏了。。。
//看紅黑樹是否還滿足其性質(分情況討論)
while (_pRoot!=pCur && pCur->_pParent->_color == RED)
{
Node* gf = parent->_pParent;//保存雙親的雙親
//gf肯定存在,因爲,如果不存在,那麼parent就是根結點,是黑色的,不會進入這個循環
//雙親在左,叔叔(存在的話)在右
if (gf->_pLeft == parent)
{
Node*uncle = gf->_pRight;
if (uncle && uncle->_color == RED) //情況一
{
parent->_color = BLACK;
uncle->_color = BLACK;
gf->_color = RED;
//向上更新
pCur = gf;
parent = pCur->_pParent;
}
else //情況二、三(將情況三轉化爲情況二,再一起處理)
{
if (parent->_pRight == pCur)
{
_RotateL(parent);
std::swap(parent, pCur);
}
gf->_color = RED;
parent->_color = BLACK;
_RotateR(gf);
}
}
else//雙親在右
{
Node*uncle = gf->_pLeft;
if (uncle && uncle->_color == RED) //情況一
{
parent->_color = BLACK;
uncle->_color = BLACK;
gf->_color = RED;
//向上更新
pCur = gf;
parent = pCur->_pParent;
}
else //情況二、三(將情況三轉化爲情況二,再一起處理)
{
if (parent->_pLeft == pCur)
{
_RotateR(parent);
std::swap(parent, pCur);
}
gf->_color = RED;
parent->_color = BLACK;
_RotateL(gf);
}
}
}
_pRoot->_color = BLACK;
return true;
}
void InOrder()
{
cout << "InOrder: ";
_InOrder(_pRoot);
cout << endl;
}
//判斷是不是紅黑樹
bool CheckRBTree()
{
if (_pRoot == NULL)
return true;
if (_pRoot->_color == RED)//違反性質2“根結點爲黑色”
return false;
size_t blackcount = 0;//統計一條鏈中黑色結點的數量
Node* pCur = _pRoot;
while (pCur)
{
if (pCur->_color == BLACK)
blackcount++;
pCur = pCur->_pLeft;//這裏以最左邊的那一條鏈爲例
}
//驗證性質4“每條鏈上的黑色結點都相等”,順便驗證性質3“紅色結點不能相連”
return _CheckRBTree(_pRoot, blackcount, 0);
}
private:
//判斷是不是紅黑樹(遞歸)
//k用來統計每一條鏈上的黑色結點的個數,但是不能給成引用,否則,再次統計下一條鏈的時候,就不會更新
bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k)
{
if (pRoot == NULL)
return true;
if (pRoot->_color == BLACK)
k++;
Node* parent = pRoot->_pParent;
if (parent && parent->_color == RED && pRoot->_color == RED)//違反性質3
return false;
if (pRoot->_pLeft == NULL&&pRoot->_pRight == NULL)
{
if (k != blackCount)//違反性質4
return false;
}
return _CheckRBTree(pRoot->_pLeft, blackCount, k)
&& _CheckRBTree(pRoot->_pRight, blackCount, k);
}
//左旋
void _RotateL(Node* parent)
{
Node* subR = parent->_pRight;
Node* subRL = subR->_pLeft;//有可能不存在
parent->_pRight = subRL;
if (subRL)
subRL->_pParent = parent;
subR->_pLeft = parent;
Node* gparent = parent->_pParent;//保存parent的雙親
parent->_pParent = subR;
if (gparent == NULL)//parent是根結點
_pRoot = subR;
else if (gparent->_pLeft == parent)
gparent->_pLeft = subR;
else
gparent->_pRight = subR;
subR->_pParent = gparent;//第三個
}
//右旋
void _RotateR(Node* parent)
{
Node*subL = parent->_pLeft;
Node*subLR = subL->_pRight;
parent->_pLeft = subLR;
if (subLR)
subL->_pParent = parent;
subL->_pRight = parent;
Node*gparent = parent->_pParent;
parent->_pParent = subL;
subL->_pParent = gparent;
if (gparent == NULL)
_pRoot = subL;
else if (gparent->_pLeft == parent)
gparent->_pLeft = subL;
else
gparent->_pRight = subL;
}
//中序遍歷
void _InOrder(Node* pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_pLeft);
cout << pRoot->_key << " ";
_InOrder(pRoot->_pRight);
}
}
//獲取最小節點
Node* _GetMinNode()
{
Node* pCur = _pRoot;
Node*parent = NULL;
while (pCur)
{
parent = pCur;
pCur = pCur->_pLeft;
}
return parent;
}
//獲取最大節點
Node* _GetMaxNode()
{
Node* pCur = _pRoot;
Node*parent = NULL;
while (pCur)
{
parent = pCur;
pCur = pCur->_pRight;
}
return parent;
}
private:
Node* _pRoot;
};
#endif
void TestRBTree()
{
int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
RBTree<int, int> t;
for (int idx = 0; idx < sizeof(a) / sizeof(a[0]); ++idx)
t.Insert(a[idx], idx);
t.InOrder();
if (t.CheckRBTree())
{
cout << "是紅黑樹" << endl;
}
else
{
cout << "不是紅黑樹" << endl;
}
}
//void TestIterator()
//{
// int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
// RBTree<int, int> t;
// for (int idx = 0; idx < sizeof(a) / sizeof(a[0]); ++idx)
// t.Insert(a[idx], idx);
// t.InOrder();
//
// RBTree<int, int>::Iterator it = t.Begin();
// while (it != t.End())
// {
// cout << *it << " ";
// ++it;
// }
//
// RBTree<int, int>::Iterator itEnd = t.End();
// --itEnd;
// cout << *itEnd << endl;
//}
int main()
{
TestRBTree();
//TestIterator();
return 0;
}