/*首先呢,按照套路,介绍一下什么是红黑树?
一、定义:
红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结
点的颜色,可以是red或者black,通过对任何一条从根节点到叶子结点上
的简单路径来约束,红黑树保证最长路径不超过最短路径的两倍,因而近视
平衡。
然后呢,我么就看一下红黑树有哪些性质呢?
二、性质:
1. 每个结点不是红色就是黑色
2. 根节点是黑色的
3. 如果一个根节点是红色的,则它的两个叶子结点是黑色的(没有两个连续
的红色结点)
4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相
同数目的黑色结点(每条路径上黑色结点的数量相等)
5. 每个叶子结点都是黑色的(*此处的叶子结点指的是空结点*)
三、接下来,就开始上干货了->红黑树的插入(ps:有图有真相哦)!
注意:cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点
1、首先呢,要想在红黑树中插入节点(默认插入节点的颜色为红色哦,读者可以思考下为什么?),我们可以分为以下几种情况:
(0)空树直接插入,并把插入结点的颜色置为红色
(0)插入节点的双亲若为黑色,直接插入
以上这两种情况灰常简单,我们就不做过多介绍了,重点介绍以下三种情况:
【情况一】
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。
是不是看着好懵逼哈,别急,接下来我们就直接上图,这样就简单明了了:
*/
![这里写图片描述](https://img-blog.csdn.net/20170527172531780?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpemhlbmdibw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![这里写图片描述](https://img-blog.csdn.net/20170527172649329?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpemhlbmdibw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![这里写图片描述](https://img-blog.csdn.net/20170527172745816?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpemhlbmdibw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![这里写图片描述](https://img-blog.csdn.net/20170527172852988?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2Vpemhlbmdibw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
#include<iostream>
#include<windows.h>
using namespace std;
enum Color{ RED, BLACK };
template<typename K, typename V>
struct RBTreeNode
{
RBTreeNode(const K& key, const V& value)
:_pLeft(NULL)
, _pRight(NULL)
, _pParent(NULL)
, _key(key)
, _value(value)
, _color(RED)
{}
RBTreeNode<K, V>*_pLeft;
RBTreeNode<K, V>*_pRight;
RBTreeNode<K, V>*_pParent;
K _key;
V _value;
Color _color;
};
template<typename K, typename V>
class RBTree
{
public:
typedef RBTreeNode<K, V> Node;
RBTree()
:_pRoot(NULL)
{}
bool Insert(const K&key, const V&value)
{
if (NULL == _pRoot)
{
_pRoot = new Node(key, value);
_pRoot->_color = BLACK;
return true;
}
Node*pCur = _pRoot;
Node*pParent = NULL;
while (pCur)
{
if (pCur->_key<key)
{
pParent = pCur;
pCur = pCur->_pRight;
}
else if (pCur->_key>key)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else
return false;
}
pCur = new Node(key, value);
if (pParent->_color == BLACK)
{
if (key > pParent->_key)
{
pParent->_pRight = pCur;
}
else
{
pParent->_pLeft = pCur;
}
pCur->_pParent = pParent;
return true;
}
else
{
if (key > pParent->_key)
{
pParent->_pRight = pCur;
}
else
{
pParent->_pLeft = pCur;
}
pCur->_pParent = pParent;
}
while (_pRoot != pCur&&RED == pParent->_color)
{
Node*GrandFather = pParent->_pParent;
if (BLACK == GrandFather->_color)
{
if (pParent == GrandFather->_pLeft)
{
Node*Uncle = GrandFather->_pRight;
if (Uncle&&Uncle->_color == RED)
{
pParent->_color = BLACK;
Uncle->_color = BLACK;
GrandFather->_color = RED;
pCur = pParent;
pParent = pParent->_pParent;
}
else
{
if (pCur == pParent->_pRight)
{
_RotateLeft(pParent);
std::swap(pCur, pParent);
}
_RotateRight(GrandFather);
pParent->_color = BLACK;
GrandFather->_color = RED;
}
}
else
{
Node*Uncle = GrandFather->_pLeft;
if (Uncle&&Uncle->_color == RED)
{
pParent->_color = BLACK;
Uncle->_color = BLACK;
GrandFather->_color = RED;
pCur = pParent;
pParent = pParent->_pParent;
}
else
{
if (pCur == pParent->_pLeft)
{
_RotateRight(pParent);
std::swap(pCur, pParent);
}
_RotateLeft(GrandFather);
pParent->_color = BLACK;
GrandFather->_color = RED;
}
}
}
_pRoot->_color = BLACK;
}
return true;
}
void InOrder()
{
cout << "InOrder:" << endl;
_InOrder(_pRoot);
cout << endl;
}
protected:
void _RotateLeft(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;
if (NULL == pPparent)
{
_pRoot = pSubR;
}
else
{
if (pParent == pPparent->_pLeft)
{
pPparent->_pLeft = pSubR;
}
else
{
pPparent->_pRight = pSubR;
}
}
pSubR->_pParent = pPparent;
}
void _RotateRight(Node*pParent)
{
Node*pSubL = pParent->_pLeft;
Node*pSubLR = pSubL->_pRight;
pParent->_pLeft = pSubLR;
if (pSubLR)
{
pSubLR->_pParent = pParent;
}
Node*pPParent = pParent->_pParent;
pParent->_pParent = pSubL;
pSubL->_pRight = pParent;
pSubL->_pParent = pPParent;
if (NULL == pPParent)
{
_pRoot = pSubL;
}
else
{
if (pPParent->_pLeft == pParent)
{
pPParent->_pLeft = pSubL;
}
else
pPParent->_pRight = pSubL;
}
}
void _InOrder(Node*pRoot)
{
if (pRoot)
{
_InOrder(pRoot->_pLeft);
cout << pRoot->_key<<" ";
_InOrder(pRoot->_pRight);
}
}
public:
bool CheckRBTree()
{
if (NULL == _pRoot)
return true;
if (NULL == _pRoot->_pLeft&&_pRoot->_pRight)
return false;
Node*pCur = _pRoot;
size_t blackcount = 0;
size_t k = 0;
while (pCur)
{
if (BLACK== pCur->_color)
{
++blackcount;
}
pCur = pCur->_pLeft;
}
return _CheckRBTree(_pRoot, blackcount, k);
}
bool _CheckRBTree(Node*pRoot, size_t _count, size_t k)
{
if (NULL == pRoot)
return true;
if (BLACK == pRoot->_color)
k++;
if (NULL == pRoot->_pLeft&&NULL == pRoot->_pRight)
{
if (_count != k)
{
cout << "树中某一路径黑颜色节点个数不同" << endl;
return false;
}
}
Node*pParent = pRoot->_pParent;
if (pParent&&RED == pParent->_color&&RED == pRoot->_color)
{
cout << "树中有两个连在一起的红色节点" << endl;
return false;
}
return _CheckRBTree(pRoot->_pLeft, _count, k) && _CheckRBTree(pRoot->_pRight, _count, k);
}
private:
Node* _pRoot;
};
void FUNRBTree()
{
RBTree<int, int>RBT;
int count = 0;
int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
for (size_t idx = 0; idx < sizeof(a) / sizeof(a[0]); idx++)
{
count++;
RBT.Insert(a[idx], idx);
}
RBT.InOrder();
bool flag = RBT.CheckRBTree();
if (flag)
cout << "是红黑树"<<endl;
else
cout << "不是红黑树" << endl;
}
int main()
{
FUNRBTree();
system("pause");
return 0;
}