红黑树的特点:
1、任意一个结点要么是红色,要么是黑色
2、根结点是黑色
3、一条路径上不能出现两个连续的红色结点
4、从根节点到任一叶子节点的黑色结点个数相同
5、NUL结点默认为黑色结点(可忽略)
插入实现
注意:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
【情况一】cur为红,p为红,g为黑,u存在且为红则将p,u改为黑,g改为红,然后把g当成cur,继续向上调整。
【情况二】cur为红,p为红,g为黑,u不存在/u为黑p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转p、g变色--p变黑,g变红
【情况三】cur为红,p为红,g为黑,u不存在/u为黑p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反,p为g的右孩子,cur为p的左孩子,则针对p做右单旋转则转换成了情况2
#pragma once
#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)
:_value(value)
,_key(key)
,_pLeft(NULL)
,_pRight(NULL)
,_pParent(NULL)
,_color(color)
{
}
K _key;
V _value;
RBTreeNode<K,V> * _pLeft;
RBTreeNode<K,V> *_pRight;
RBTreeNode<K,V> *_pParent;
Color _color; //节点的颜色。
};
//红黑树迭代器实现
template<class K, class V, class Ref, class Ptr>
class Iterator
{
public:
typedef RBTreeNode<K,V> Node;
typedef Iterator<K,V,Ref,Ptr> Self;
Iterator():_pNode(NULL) { }
Iterator(Node *Root):_pNode(Root) { }
Iterator(const Self & it):_pNode(it._pNode){ }
Ref operator*()
{
return _pNode->_key;
}
Ptr operator->()
{
return &(operator*() );
}
Self& operator++()
{
_pNode = Increment();
return *this;
}
Self operator++(int)
{
Self temp(*this);
_pNode = Increment();
return temp;
}
Self& operator--()
{
_pNode = Decrement();
return *this;
}
Self operator--(int)
{
Self temp(*this);
_pNode = Decrement();
return temp;
}
bool operator==(const Self & it)
{
return _pNode == it._pNode;
}
bool operator != (const Self & it)
{
return _pNode != it._pNode;
}
private:
Node* Increment()
{
Node *pCur = _pNode;
if (pCur->_pRight) //当右子树存在,当前节点的下一个节点就是右子树的最左节点。
{
Node *pRight = pCur->_pRight;
while (pRight->_pLeft)
{
pRight = pRight->_pLeft;
}
pCur = pRight;
}
else //右子树不存在。
{
Node *pParent = pCur->_pParent;
while (pParent->_pRight == pCur)
{
pCur = pParent;
pParent = pParent->_pParent;
}
if ( pCur->_pRight != pParent) //特殊情况,最后一个节点还能再++,++后指向end().
{
pCur = pParent;
}
}
return pCur;
}
Node* Decrement()
{
Node *pCur = _pNode;
if (RED == pCur->_color && pCur->_pParent->_pParent == pNode)//特殊情况在end()的位置
pCur = pCur->_pRight;
else if (pCur->_pLeft) //当左子树存在,当前节点的下一个节点就是左子树的最右节点。
{
Node *pLeft = pCur->_pLeft;
while (pRight->_pLeft)
{
pRight = pRight->_pLeft;
}
pCur = pRight;
}
else //左子树不存在。
{
Node *pParent = pCur->_pParent;
while (pParent->_pLeft == pCur)
{
pCur = pParent;
pParent = pParent->_pParent;
}
pCur = pParent; //第一个节点不能再减了,如果减就是随机值
}
return pCur;
}
private:
Node *_pNode;
};
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
typedef Iterator<K,V,K&,K*> Iterator;
public:
RBTree(): _pHead(NULL)
{
_pHead = new Node(0,0);
_pHead->_pLeft = _pHead;
_pHead->_pRight = _pHead;
}
Iterator Begin()
{
return Iterator(_pHead->_pLeft);
}
Iterator End()
{
return Iterator(_pHead);
}
Node *GetMaxNode()
{
Node *pCur = GetRoot();
while (pCur->_pRight)//不需要判空 在insert中调用 不会为空
pCur = pCur->_pRight;
return pCur;
}
Node *GetMinNode()
{
Node *pCur = GetRoot();
while (pCur->_pLeft)//不需要判空 在insert中调用 不会为空
pCur = pCur->_pLeft;
return pCur;
}
bool Insert(const K& key, const V& value)
{
Node *& pRoot= GetRoot();
if (pRoot == NULL)
{
pRoot = new Node(key,value);
pRoot->_color = BLACK;
pRoot->_pParent = _pHead;
return true;
}
Node *pCur = pRoot;
Node *pParent = NULL;
while (pCur)
{
if (key < pCur->_key)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else if (key == pCur->_key)
{
return false;
}
else
{
pParent = pCur;
pCur = pCur->_pRight;
}
}
pCur = new Node(key,value);
if (key < pParent->_key)
{
pParent->_pLeft = pCur;
pCur->_pParent = pParent;
}
else
{
pParent->_pRight = pCur;
pCur->_pParent = pParent;
}
//调整颜色。
while (pCur != pRoot && pParent->_color == RED ) //根不需要调整,因为退了这个循环直接把根的颜色改成黑色。
{
Node *garndFather = pParent->_pParent;
Node *uncle = NULL;
if (pParent == garndFather->_pRight)
{
uncle = garndFather->_pLeft;
}
else
uncle = garndFather->_pRight;
if (uncle != NULL && uncle->_color == RED) //unclue存在且为红
{
pParent->_color = BLACK;
uncle->_color = BLACK;
garndFather->_color = RED;
}
else //u不存在或者u为黑。
{
if (pParent == garndFather->_pLeft) //父亲是爷爷的左孩子
{
if (pCur == pParent->_pRight)
{
RotateLeft(pParent);
swap(pParent,pCur);
}
if (pCur == pParent->_pLeft)
{
RotateRight(garndFather);
pParent->_color = BLACK;
garndFather->_color = RED;
}
}
else //父亲是爷爷的右孩子。
{
if (pCur == pParent->_pLeft)
{
RotateRight(pParent);
swap(pParent,pCur);
}
if (pCur == pParent->_pRight)
{
RotateLeft(garndFather);
pParent->_color = BLACK;
garndFather->_color = RED;
}
}
}
pCur = garndFather;
pParent = pCur->_pParent;
}
_pHead->_pLeft = GetMinNode();
_pHead->_pRight = GetMaxNode();
pRoot->_color = BLACK;
return true;
}
void RotateLeft(Node* parent)
{
Node *pparent = parent->_pParent;
Node *subR = parent->_pRight;
Node *subRL = subR->_pLeft;
if(pparent == _pHead)
{
Node *& pRoot = GetRoot();
pRoot = subR;
}
else
{
if (parent == pparent->_pLeft)
{
pparent->_pLeft = subR;
}
else
{
pparent->_pRight = subR;
}
}
subR->_pParent = pparent;
subR->_pLeft = parent;
parent->_pParent = subR;
parent->_pRight = subRL;
if (subRL != NULL)
{
subRL->_pParent = parent;
}
}
void RotateRight(Node* parent)
{
Node * subL = parent->_pLeft;
Node *subLR = subL->_pRight;
Node *pparent = parent->_pParent;
if (pparent == _pHead)
{
Node *& pRoot = GetRoot();
pRoot = subL;
}
else
{
if (parent == pparent->_pLeft)
{
pparent->_pLeft = subL;
}
else
{
pparent->_pRight = subL;
}
}
subL->_pParent = pparent;
subL->_pRight = parent;
parent->_pParent = subL;
parent->_pLeft = subLR;
if (subLR != NULL)
{
subLR->_pParent = parent;
}
}
void InOrder()
{
Node *&pRoot = GetRoot();
_InOrder(pRoot);
}
void _InOrder(Node* pRoot)
{
if(pRoot)
{
_InOrder(pRoot->_pLeft);
cout<<pRoot->_key<<" ";
_InOrder(pRoot->_pRight);
}
}
//检查是不是红黑树
bool CheckRBTree()
{
Node *&pRoot = GetRoot();
if (pRoot == NULL)
{
return true;
}
if (pRoot->_color == RED)
{
return false;
}
//找到一条路径上黑色节点的个数
size_t blackCount = 0;
Node *pCur = pRoot;
while (pCur)
{
if (pCur->_color == BLACK)
{
blackCount++;
}
pCur = pCur->_pLeft;
}
size_t k = 0;
return _CheckRBTree(pRoot,blackCount,k);
}
//每一条路径上的黑色节点都要相等才是红黑树。
bool _CheckRBTree(Node* pRoot, const size_t blackCount, size_t k) //这个地方k一定是值的,假设一条路径 黑-红-黑-黑-红-黑-黑-红-黑 这条路径黑色节点个数为6,现在回溯
{ // △,假设回溯到这个节点,如果是引用的话,k还是6,
if (pRoot == NULL) //如果你想回溯一次减一,但是回溯的节点可能不是黑色节点,所以引用不行
{ // 值的话,现在就是4了,符号要求
return true;
}
//当出现两个连续的红色节点的时候,可以确定不是红黑树
if (pRoot->_pParent && pRoot->_color == RED && pRoot->_pParent->_color == RED)
{
return false;
}
//如果是黑节点,k++
if (pRoot->_color == BLACK)
{
k++;
}
//如果是叶子节点的话,进行判断k和count是否相等
if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
{
if (k != blackCount)
{
return false;
}
}
return _CheckRBTree(pRoot->_pLeft,blackCount,k) && _CheckRBTree(pRoot->_pRight,blackCount,k);
}
private:
Node* _pHead; //红黑树加上一个头节点进行迭代器操作(头节点的左孩子指向红黑树的最小值,右孩子指向最大值,parent域指向根节点)
private:
Node * & GetRoot()
{
return _pHead->_pParent;
}
};
#include "RBTree.h"
void Test()
{
//int a[] = {10, 8, 7, 15, 5, 6, 11, 13, 12};
int a[] = {15,14,13,12,11,10,9,8,7,6,5,1,3,2,1,0};
RBTree<int, int> bt;
for (size_t idx = 0; idx < sizeof(a)/sizeof(a[0]); ++idx)
bt.Insert(a[idx], a[idx]);
//bt.InOrder();
cout << endl;
Iterator<int, int, int&, int *> it = bt.Begin();
//cout << "begin()" << *it <<endl;
while (it != bt.End())
{
cout << *it << " ";
it++;
}
cout <<endl;
//cout << bt.CheckRBTree() <<endl;
}
int main()
{
Test();
system("pause");
return 0;
}
红黑树和AVL树的比较
红黑树和AVL树都是高效的平衡二叉树,增删查改的时间复杂度都是O(lg(N))红黑树的不追求完全平衡,保证最长路径不超过最短路径的2倍,相对而言,降低了旋转的要求,所以性能跟AVL树差不多,但是红黑树实现更简单,所以实际运用中红黑树更多。