1.0 红黑树的特性:
前提:红黑树也是特殊的二叉搜索树
(1) 每个节点或者是黑色,或者是红色。(2) 根节点是黑色。
(3) 每个叶子节点是黑色。 [ 注意:这里叶子节点,是指为空的叶子节点!]
(4) 如果一个节点是红色的,则它的子节点必须是黑色的。
(5) 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相 同数目的黑色结点(每条路径上黑色结点的数量相等) 。
2.0 主要操作: 节点插入 Insert函数的实现
考虑1:满足上面的颜色约束性质,红黑树能保证最长路径不超过最短路径的两倍?
极限情况:
插入黑色节点,不满足特性5
插入红色节点,不满足特性4
考虑2:节点构造时,必须有颜色这个成员,默认颜色给什么好?
所以,节点默认颜色红色比较好。
左单旋,右单旋请参考:点击打开链接
3.0 插入的具体情况:
情况1: 树为空,则将插入的节点颜色改为黑色即可(因为默认为红色节点)。
情况2: 插入节点的双亲节点为黑色,不违反规则,什么都不改。
插入节点的双亲节点为红色时,需要作出变色以及旋转处理:
定义:cur为当前节点,p为其双亲节点,g为其祖父节点,u为其叔叔节点。
情况3: u存在且为红色,处理过程为下图:
4:
情况4: u不存在,或者u存在且为黑色,处理过程为下图: g变为红色,p变为黑色
情况5: 同情况4,不过cur为parent的右孩子,处理过成如下图:
4.0 实现代码:
RBtree.h
#pragma once
#include<iostream>
using namespace std;
enum COLOR {RED,BLACK};
template <class k,class v >
struct RBTreeNode
{
RBTreeNode(k key,v value,COLOR color=RED)
: _left(NULL)
, _right(NULL)
, _parent(NULL)
, _value(key,value)
, _color(color)
{}
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
pair<k, v> _value;
COLOR _color;
};
template <class k, class v >
class RBTree
{
typedef RBTreeNode<k, v> Node;
typedef Node* PNode;
public:
//构造函数
RBTree()
:_root(NULL)
{}
bool InsertUnique(const pair<k, v>& value)
{
return _InsertUnique(value, _root);
}
void InOrder()
{
_InOrder(_root);
}
bool IsRBtree()
{
if (NULL == _root) //空树也是红黑树
return true;
if (_root->_color == RED) //不满足性质2
{
cout <<"根节点为红色违反性质2"<< endl;
return false;
}
//统计一条路径上的黑色节点个数(用count计数)
PNode PCur = _root;
size_t count = 0;
while (PCur)
{
if (PCur->_color == BLACK)
count++;
PCur = PCur->_left;
}
size_t i = 0;
return _IsRBtree(_root, count,i); //传参i的原因:递归实现需要记录黑色节点个数
} //而返回至该层时,期望i还是该层的值所以传值
protected:
bool _InsertUnique(const pair<k, v>& value, PNode& _root)
{
if (NULL == _root)
{
_root = new Node(value.first, value.second, BLACK);
return true;
}
//找待插入节点的位置
PNode PCur = _root;
PNode parent = PCur;
while (PCur)
{
parent = PCur;
if (value.first > PCur->_value.first)
PCur = PCur->_right;
else if (value.first < PCur->_value.first)
PCur = PCur->_left;
else
return false;
}
//插入新节点 PCur==NULL
PCur = new Node(value.first, value.second);
if (value.first > parent->_value.first)
{
parent->_right = PCur;
}
else
{
parent->_left = PCur;
}
PCur->_parent = parent;
//更新节点颜色(红红相连不满足特性3)
while (parent && parent->_color == RED)
{
PNode grandfather = parent->_parent;
if (grandfather->_left == parent) //总的两种(1.parent,PCur均在grandfather的左侧)
{
PNode uncle = grandfather->_right;
if (uncle && uncle->_color == RED) //情况3
{
uncle->_color = BLACK;
parent->_color = BLACK;
grandfather->_color = RED;
//向上更新PCur和parent
PCur = grandfather;
parent = PCur->_parent;
}
else //uncle不存在或者uncle->_color == BLACK
{
if (PCur == parent->_right) //情况5
{
RotateL(parent);
swap(PCur, parent); //交换指针指向之后才和情况4完全一致
}
parent->_color = BLACK; //情况4,5的共同代码
grandfather->_color = RED;
RotateR(grandfather);
}
}
else // 2.parent,PCur均在grandfathe的右侧
{
PNode uncle = grandfather->_left;
if (uncle && uncle->_color == RED) //情况3
{
uncle->_color = BLACK;
parent->_color = BLACK;
grandfather->_color = RED;
//向上更新PCur和parent
PCur = grandfather;
parent = PCur->_parent;
}
else //uncle不存在或者uncle->_color == BLACK
{
if (PCur == parent->_left) //情况5
{
RotateR(parent);
swap(PCur, parent); //交换指针指向之后才和情况4完全一致
}
parent->_color = BLACK; //情况4,5的共同代码
grandfather->_color = RED;
RotateL(grandfather);
}
}
}
_root->_color = BLACK; //循环外统一将_root->_color=BLACK
return true;
}
void RotateL(PNode parent)
{
PNode PSubR = parent->_right;
PNode PSubRL = PSubR->_left;
parent->_right = PSubRL;
if (PSubRL)
PSubRL->_parent = parent;
PSubR->_left = parent;
PNode pparent = parent->_parent;
PSubR->_parent = pparent;
parent->_parent = PSubR;
if (NULL == pparent)
_root = PSubR;
else
{
if (pparent->_left == parent)
pparent->_left = PSubR;
else
pparent->_right = PSubR;
}
}
void RotateR(PNode parent)
{
PNode PSubL = parent->_left;
PNode PSubLR = PSubL->_right;
parent->_left = PSubLR;
if (PSubLR)
PSubLR->_parent = parent;
PSubL->_right = parent;
PNode pparent = parent->_parent;
PSubL->_parent = pparent;
parent->_parent = PSubL;
if (NULL == pparent)
_root = PSubL;
else
{
if (pparent->_left == parent)
pparent->_left = PSubL;
else
pparent->_right = PSubL;
}
}
void _InOrder(PNode _root)
{
if (_root)
{
_InOrder(_root->_left);
cout << _root->_value.first << "," << _root->_value.second << " ";
_InOrder(_root->_right);
}
}
bool _IsRBtree(PNode _root,size_t count,size_t i)
{
if (NULL == _root) //空树也是红黑树
return true;
if (_root->_color == BLACK)
i++;
PNode parent = _root->_parent;
if (parent&&_root->_color == RED&&parent->_color == RED)
{
cout <<"红红相连违反性质3"<< endl;
return false;
}
if (NULL == _root->_left&&NULL == _root->_right) //叶子结点
{
if (i != count)
{
cout << "路径中黑色节点的个数不相等违反性质4" << endl;
return false;
}
}
return _IsRBtree( _root->_left,count,i )&&_IsRBtree( _root->_right, count,i );
}
private:
PNode _root;
};
void RBtreeTest()
{
int a[] = { 10, 7, 8, 15, 5, 6, 11, 13, 12 };
int size = sizeof(a) / sizeof(a[0]);
RBTree<int, int> rbt;
for (int i = 0; i < size; ++i)
rbt.InsertUnique(pair<int, int>(a[i],i));
//rbt.InsertUnique(make_pair(a[i], i)); 等价
rbt.InOrder();
cout << endl;
cout<<rbt.IsRBtree();
}
main.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include"RBtree.h"
#include<iostream>
using namespace std;
int main()
{
RBtreeTest();
system("pause");
return 0;
}
结果: