RBTree
RBTree:红黑树是一棵二叉搜索树,它在每个节点上增加了一个存储位来表示节点的颜色,可以是Red或Black。通过对任何一条从根到叶子简单路径上的颜色来约束,红黑树保证最长路径不超过最短路径的两倍,因而近似于平衡。
红黑树是平衡二叉搜索树的一种(平衡二叉搜索树中又有AVL Tree),满足二叉搜索树的条件外,还应买足下面的4个条件:
1. 每个节点不是红色就是黑色;
2.根节点是黑色;
3.如果节点是红,那么子节点为黑色;(所以新增节点的父节点为黑色)
4.任一节点到NULL(树尾端)的任何路径,所含的黑节点数必须相同;(所以新增节点为红色)
ps: 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。
RBTree和AVLTree的对比:
红黑树和AVL树都是高效的平衡二叉树,增删查改的时间复杂度都是O(lg(N)),红黑树的不追求完全平衡,保证最长路径不超过最短路径的2倍,相对而言,降低了旋转的要求,所以性能会优于AVL树,所以实际运用中红黑树更多。
RBTree的应用:STL里边map和set,linux内核
#pragma once
#include <iostream>
using namespace std;
#include <stdio.h>
enum Colour
{
RED,
BLACK,
};
template<class K, class V>
struct RBTreeNode
{
K _key;
V _value;
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
Colour _colour; //类中枚举
RBTreeNode(const K& key, const V& value) //拷贝构造
:_key(key)
, _value(value)
, _left(NULL)
, _right(NULL)
, _parent(NULL)
, _colour(RED)
{}
};
template<class K, class V>
struct RBTree
{
typedef RBTreeNode<K, V> Node;
public:
RBTree()
:_root(NULL)
{}
bool Insert(const K& key, const V& value) //插入
{
if (_root == NULL)
{
_root = new Node(key, value);
_root->_colour = BLACK;
return true;
}
Node* parent = NULL;
Node* cur = _root;
while (cur)//从根开始遍历
{
if (cur->_key < key)//插入值大于根 往右子树遍历
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)//左
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
// cur 即为要插入的位置
// parent 即为原始叶子节点
cur = new Node(key, value);
cur->_colour = RED; // 插入的先预设为红 如果为黑 对整个树的影响过大
//重建树的链式结构
if (parent->_key < key)
{
parent->_right = cur;
cur->_parent = parent;
}
else
{
parent->_left = cur;
cur->_parent = parent;
}
// 旋转变化
while (parent && parent->_colour == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left) //左
{
Node* uncle = grandfather->_right; //由uncle决定怎么变化
// 1.存在且为红
// 2.不存在,存在且为黑
if (uncle && uncle->_colour == RED)
{
parent->_colour = uncle->_colour = BLACK;
grandfather->_colour = RED;
cur = grandfather; // 往上推 看是否影响其他的节点
parent = cur->_parent;//
}
else
{
if (parent->_right == cur) //右边 左右双旋
{
RotateL(parent); //左旋
swap(cur, parent);
}
RotateR(grandfather); // 只右旋 一次
parent->_colour = BLACK;
grandfather->_colour = RED;
}
}
else
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_colour == RED)
{
parent->_colour = BLACK;
uncle->_colour = BLACK;
grandfather->_colour = RED;
// 继续往上更新
cur = grandfather;
parent = cur->_parent;
}
else // 不存在 / 存在且为黑
{
if (cur == parent->_left) // 左边 右左双旋
{
RotateR(parent);
swap(cur, parent);
}
RotateL(grandfather);// 右边 只旋转一次 左旋
parent->_colour = BLACK;
grandfather->_colour = RED;
}
}
}
_root->_colour = BLACK; //暴力格式化根为黑
return true;
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* ppNode = parent->_parent;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
subL->_parent = NULL;
}
else
{
if (ppNode->_right == parent)
{
ppNode->_right = subL;
}
else
{
ppNode->_left = subL;
}
subL->_parent = ppNode;
}
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* ppNode = parent->_parent;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
subR->_left = parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
_root->_parent = NULL;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
void InOrder() //析构函数
{
_InOrder(_root);
}
void _InOrder(Node* root)
{
if (root == NULL)
{
return;
}
_InOrder(root->_left);
cout << root->_key << " ";
_InOrder(root->_right);
}
bool _IsBalance(Node* root, size_t blackNum, const size_t N)
{
if (root == NULL)
{
if (N != blackNum)
{
cout << "黑色节点的数量不相等" << endl;
return false;
}
else
{
return true;
}
}
if (root->_colour == BLACK)
{
++blackNum;
}
if (root->_colour == RED
&& root->_parent->_colour == RED)
{
cout << "存在连续的红节点" << _root->_key << endl;
return false;
}
return _IsBalance(root->_left, blackNum, N)
&& _IsBalance(root->_right, blackNum, N);
}
bool IsBalance()
{
if (_root && _root->_colour == RED)
{
return false;
}
size_t N = 0;
Node* cur = _root;
while (cur)
{
if (cur->_colour == BLACK)
{
++N; //每条路径上的黑色节点数相同 故只用求一次单链的黑色节点数
}
cur = cur->_left;
}
size_t blackNum = 0;
return _IsBalance(_root, blackNum, N);
}
private:
Node* _root;
};
void TestRBTree()
{
//int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
//RBTree<int, int> t;
//for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
//{
// t.Insert(a[i], i);
//}
//t.InOrder();
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
RBTree<int, int> t;
for (size_t i = 0; i < sizeof(a)/sizeof(a[0]); ++i)
{
t.Insert(a[i], i);
cout<<a[i]<<"->IsBalance?"<<t.IsBalance()<<endl;
}
cout<<"IsBalance?"<<t.IsBalance()<<endl;
t.InOrder();
}
AVLTree:https://blog.csdn.net/Romantic_C/article/details/81262703