红黑树:红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,可以是red或者black,通过对任何一条从根节点到叶子结点上的简单路径来约束,红黑树保证最长路径不超过最短路径的两倍,因而近视平衡。
性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个根节点是红色的,则它的两个叶子结点是黑色的(没有两个连续
的红色结点)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相
同数目的黑色结点(每条路径上黑色结点的数量相等)
5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)
插入的实现:
pCur为当前结点,parent为父亲结点,uncle为叔叔结点,grandpa为祖父结点
第一种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle存在且为红色
做如下调整:parent改为黑色,grandpa改为红色,uncle改为黑色
第二种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle不存在或存在且为黑色
做如下调整:grandpa的左孩子为parent,parent的左孩子为pCur时,对grandpa进行右单旋,parent改为黑色,grandpa改为红色;
grandpa的右孩子为parent,parent的右孩子为pCur时,对grandpa进行左单旋,parent改为黑色,grandpa改为红色;
第三种情况:
pCur为红色,parent为红色,grandpa为黑色,uncle不存在或存在且为黑色
做如下调整:grandpa的左孩子为parent,parent的右孩子为pCur时,先对parent进行左单旋并交换pCur和parent,然后对grandpa进行右单旋,pCurt改为黑色,grandpa改为红色;
grandpa的右孩子为parent,parent的左孩子为pCur时,先对parent进行右单旋并交换pCur和parent,然后对grandpa进行左单旋,pCurt改为黑色,grandpa改为红色;
完整代码如下:
rbt.cpp
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
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)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
, _color(color)
{}
K _key;
V _value;
RBTreeNode<K,V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
Color _color;
};
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 (NULL == _pRoot)
{
_pRoot = new Node(key, value);
return true;
}
//寻找插入位置
Node* pCur = _pRoot;
Node* parent = NULL;
while (pCur)
{
if (pCur->_key < key)
{
parent = pCur;
pCur = pCur->_right;
}
else if (pCur->_key>key)
{
parent = pCur;
pCur = pCur->_left;
}
else
{
return false;
}
}
//插入结点
pCur = new Node(key, value);
if (parent->_key > key)
{
parent->_left=pCur;
pCur->_parent = parent;
}
else
{
parent->_right=pCur;
pCur->_parent = parent;
}
while (parent != _pRoot && parent->_color == RED)
{
Node* grandpa = parent->_parent;
if ( grandpa->_left==parent)
{
Node* uncle = grandpa->_right;
{
Node* uncle = grandpa->_right;
//叔叔结点存在且为红色
if (uncle &&uncle->_color == RED)
{
parent->_color = BLACK;
uncle->_color = BLACK;
grandpa->_color = RED;
//继续向上调整
pCur = grandpa;
parent = pCur->_parent;
}
//叔叔结点不存在或叔叔结点存在为黑色
else
{
//pCur为parent的右孩子
if (pCur == parent->_right)
{
RotateL(parent);
swap(pCur, parent);
}
parent->_color = BLACK;
grandpa->_color = RED;
RotateR(grandpa);
break;
}
}
}
//parent=grandpa->_right
else
{
Node* uncle = grandpa->_left;
//叔叔结点存在且为红色
if (uncle &&uncle->_color == RED)
{
parent->_color = BLACK;
uncle->_color = BLACK;
grandpa->_color = RED;
//继续向上调整
pCur = grandpa;
parent = pCur->_parent;
}
else
{
//pCur为parent的左孩子
if (pCur == parent->_left)
{
RotateR(parent);
swap(pCur, parent);
}
parent->_color = BLACK;
grandpa->_color = RED;
RotateL(grandpa);
break;
}
}
_pRoot->_color = BLACK;
return true;
}
}
//中序遍历
void Inorder()
{
return _Inorder(_pRoot);
}
//查找结点
bool Find(const K& key)
{
Node* pCur = _pRoot;
if (pCur == NULL)
return false;
else
{
while (pCur)
{
if (pCur->_key < key)
pCur = pCur->_right;
else if (pCur->_key>key)
pCur = pCur->_left;
else
return true;
}
}
return true;
}
//判断是否平衡
bool IsBalance()
{
if (NULL == _pRoot)
return true;
if (_pRoot->_color == RED)
return false;
int k = 0;
Node* pCur = _pRoot;
while (pCur)
{
//记录其中一条路径黑色结点个数
if (pCur->_color == BLACK)
++k;
pCur = pCur->_left;
}
//另一条路径黑色结点个数
int count = 0;
return _IsBalance(_pRoot, k, count);
}
//左旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
subR->_left = parent;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* pparent = parent->_parent;
if (NULL == pparent)
{
_pRoot = subR;
subR->_parent = NULL;
}
else
{
if (pparent->_left == parent)
pparent->_left = subR;
else
pparent->_right = subR;
subR->_parent = pparent;
}
parent->_parent = subR;
}
//右旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
subL->_right = parent;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* pparent = parent->_parent;
if (NULL == pparent)
{
_pRoot = subL;
subL->_parent = NULL;
}
else
{
if (pparent->_left == parent)
pparent->_left = subL;
else
pparent->_right = subL;
subL->_parent = pparent;
}
parent->_parent = subL;
}
void _Inorder(Node* pRoot)
{
if (NULL == pRoot)
return ;
_Inorder(pRoot->_left);
cout << pRoot->_key << "->";
_Inorder(pRoot->_right);
}
bool _IsBalance(Node* pRoot, int k, int count)
{
if (NULL == pRoot)
return true;
if (pRoot->_color == RED)
{
if (pRoot->_parent&&pRoot->_parent->_color == RED)
return false;
}
else
count++;
if (pRoot->_left == NULL&&pRoot->_right == NULL)
{
//比较两条路径黑色结点个数
if (k == count)
return true;
else
return false;
}
return _IsBalance(pRoot->_left, k, count) && _IsBalance(pRoot->_left, k, count);
}
private:
Node* _pRoot;
};
void test()
{
RBTree<int, int> rbt;
/*int array[] = {5,2,1,3,4,0,7,8,6};
int size = sizeof(array) / sizeof(array[0]);
for (int i = 0; i < size; i++)
{
rbt.Insert(array[i],i);
}*/
rbt.Insert(5, 5);
rbt.Insert(2, 2);
rbt.Insert(1, 1);
rbt.Insert(3, 3);
rbt.Insert(4, 4);
rbt.Insert(0, 0);
rbt.Insert(7, 7);
rbt.Insert(8, 8);
rbt.Insert(6, 6);
rbt.Inorder();
cout << "\n";
cout<<rbt.Find(5)<<endl;
cout << "\n";
cout << rbt.IsBalance() << endl;
}
int main()
{
test();
system("pause");
return 0;
}