创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。
提示:以下是本篇文章正文内容,下面案例可供参考
一、红黑树
1.红黑树的概念
2.红黑树的性质
满足上面的性质,红黑树就能保证:其最长路径中节点个数不会超过最短路径节点
个数的两倍。

注意:路径是从根节点走到空
3.红黑树节点的定义
//RBTree.h
enum Color {
RED,
BLACK
};
template<class K, class V>
struct RBTreeNode
{
RBTreeNode<K, V>* left;
RBTreeNode<K, V>* right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Color col;
RBTreeNode(const pair<K, V>& kv)
:left(nullptr)
,right(nullptr)
, _parent(nullptr)
, _kv(kv)
,col(RED)
{}
};
4.节点的插入
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->col = BLACK;
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->left;
}
else
return false;
}
cur = new Node(kv);
cur->col = RED;
if (parent->_kv.first < kv.first)
{
parent->right = cur;
cur->_parent = parent;
}
else
{
parent->left = cur;
cur->_parent = parent;
}
while (parent&& parent->col == RED)
{
Node* grandfather = parent->_parent;
//具体情况后面分析
.
.
.
.
.
.
}
_root->col = BLACK;
return true;
}
private:
Node* _root = nullptr;
};
新节点的默认颜色是红色,因此:如果
其双亲节点的颜色是黑色,没有违反红黑树任何
性质
,则不需要调整;但
当新插入节点的双亲节点颜色为红色时,就违反了性质三不能有连
在一起的红色节点,此时需要对红黑树分情况来讨论:约定
:cur
为当前节点,
p
为父节点,
g
为祖父节点,
u
为叔叔节点。
下面以parent在左子树为例:
①cur为红,p为红,g为黑,u存在且为红
if (parent == grandfather->left)
{
// g
// p u
// c
Node* uncle = grandfather->right;
if (uncle && uncle->col == RED)
{
// 变色
parent->col = uncle->col = BLACK;
grandfather->col = RED;
// 继续往上更新处理
cur = grandfather;
parent = cur->_parent;
}
else
{
// ②cur为红,p为红,g为黑,u不存在/u存在且为黑
}
}
②cur为红,p为红,g为黑,u不存在/u存在且为黑
Ⅰ.u不存在的情况
Ⅱ.u存在且为黑
cur一定是新增在下面子树的位置,通过变换上来的。
解决方案:p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反,p为g的右孩子,cur为p的右孩子,则进行左单旋转;p、g变色:p变黑,g变红
p
为
g
的左孩子,
cur
为
p
的右孩子,则针对
p做左单旋转,再对g右单旋转;
相反 ,
p
为
g
的右孩子,
cur
为
p
的左孩子,则针对
p做右单旋转,再对g左单旋转。
else
{
if (cur == parent->left)
{
// 单旋
// g
// p
// c
RotateR(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else
{
// 双旋
// g
// p
// c
RotateL(parent);
RotateR(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
右子树情况类似于左子树:
else // parent == grandfather->right
{
// g
// u p
// c
Node* uncle = grandfather->left;
if (uncle && uncle->col == RED)
{
// 变色
parent->col = uncle->col = BLACK;
grandfather->col = RED;
// 继续往上处理
cur = grandfather;
parent = cur->_parent;
}
else
{
if (cur == parent->right)
{
RotateL(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else
{
// g
// u p
// c
//
RotateR(parent);
RotateL(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
}
//Test.cpp
#include<iostream>
using namespace std;
#include"RBTree.h"
int main()
{
//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
RBTree<int, int> t;
for (auto e : a)
{
t.Insert(make_pair(e, e));
}
t.InOrder();
return 0;
}
5.红黑树的验证
// 根节点->当前节点这条路径的黑色节点的数量
bool Check(Node* root, int blacknum, const int refVal)
{
if (root == nullptr)
{
if (blacknum != refVal)
{
cout << "存在黑色节点数量不相等的路径" << endl;
return false;
}
return true;
}
if (root->col == RED && root->_parent->col == RED)
{
cout << "有连续的红色节点" << endl;
return false;
}
if (root->col == BLACK)
++blacknum;
return Check(root->left, blacknum, refVal)
&& Check(root->right, blacknum, refVal);
}
bool IsBalance()
{
if (_root == nullptr)
return true;
if (_root->col == RED)
return false;
//参考值
int refVal = 0;
Node* cur = _root;
while (cur)
{
if (cur->col == BLACK)
{
++refVal;
}
cur = cur->left;
}
int blacknum = 0;
return Check(_root, blacknum, refVal);
}
总结
以上就是今天要讲的内容,本文仅仅简单介绍了c++的基础知识。