总特征:任意节点到叶子节点的最长路径不超过最短路径的两倍
1.每个节点非红即黑
2.根节点为黑色
3.如果一个节点为红色,那么它的子节点必须是黑色(不能有连续的红节点)
4.对于某个节点来说,该节点到所有叶子节点的路径上的黑色节点数量相同
5.每个叶节点是黑色(这里的黑色包括NULL和树的尾端)
图片来自百度百科
话不多说,直接用C++实现红黑树的结构
enum Colour
{
RED,
BLACK
};
template <class K, class V>
struct RBTreeNode
{
pair<K, V> _kv;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode(pair<K, V> kv)
:_kv(kv)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
template <class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv);
bool IsRBTree();
void Inorder() { _Inorder(_root); }
void Leorder() { _Leorder(_root); }
private:
void RotateL(Node* root);
void RotateR(Node* root);
int _HeightGreater(Node* root);
int _HeightLess(Node* root);
bool _IsRBTree(Node* root, int k, int blackCount);
void _Inorder(Node* root);
void _Leorder(Node* root);
private:
Node* _root = nullptr;
};
插入节点颜色都是红色,因为如果插入节点为黑色,一定不符合任意节点到其所有叶子节点的黑色节点数量相同的规则,但插入节点为红色,可以根据红黑树的规则进行一定的调整,使其重新满足红黑树的性质
g是祖父节点,p是父节点,u是叔叔节点,cur可能是当前插入节点,也可能是a或b子树调整后的祖父节点
关于其中涉及到的旋转,在AVL的插入讲解这篇博客中有详细介绍
第一种情况:
最后:
第二种情况:
总结:
第三种情况:
template <class K, class V>
bool RBTree<K, V>::Insert(const pair<K, V>& kv)
{
// 以搜索二叉树的规则插入
if (_root == nullptr)
{
_root = new Node(kv);
// 根节点为黑色
_root->_col = BLACK;
return true;
}
Node* cur = _root;
Node* parent = nullptr;
// 找合适的插入位置
while (cur)
{
if (kv.first < cur->_kv.first)
{
parent = cur;
cur = cur->_left;
}
else if (kv.first > cur->_kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
cur = new Node(kv);
// 判断该插入parent的哪边
if (kv.first < parent->_kv.first)
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
// 插入结束
// 保持平衡
while (parent && parent->_col == RED) // 出现连续的红节点
{
Node* grandParent = parent->_parent;
assert(grandParent);
if (grandParent->_left == parent) // parent在祖父节点左边
{
Node* uncle = grandParent->_right;
// u为红色,一定要提前判断u是否存在
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
grandParent->_col = BLACK;
return true;
}
else // grandParent不是根节点,但其父节点为黑色,也插入完成
{
if (grandParent->_parent && grandParent->_parent->_col == BLACK)
{
return true;
}
else // grandParent的父节点为红,出现连续红节点,更新节点,继续调整
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
// cur在p的左边
if (cur == parent->_left)
{
RotateR(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateL(parent);
RotateR(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return true;
}
} // end of - if (grandParent->_left == parent)
else // p在grandParent的右边
{
Node* uncle = grandParent->_left;
assert(grandParent);
// u为红色
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
_root->_col = BLACK;
return true;
}
else
{
if (grandParent->_parent && grandParent->_parent->_col == BLACK)
{
return true;
}
// 更新继续调整
else
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
// cur在p的右边
if (cur == parent->_right)
{
RotateL(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateR(parent);
RotateL(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return true;
}
} // end of - else
}// end if - while
return true;
}
先求出一条路径上的黑色节点数量blackCount,然后调用子函数,子函数递归整棵树,用k记录当前路径的黑色节点数量,遇到黑色节点k++,当遇到节点为空的情况,比较k与blackCount是否相等。
另外每次递归要判断
template <class K, class V>
bool RBTree<K, V>::_IsRBTree(Node* cur, int k, int blackCount)
{
if (cur == nullptr)
{
if (blackCount != k)
{
cout << "路径上的黑色节点数量不相等" << endl;
return false;
}
return true;
}
if (_root->_col != BLACK)
{
cout << "根节点为红色" << endl;
return false;
}
// 求以cur为根节点的最小高度与最大高度
int less = _HeightLess(cur);
int greater = _HeightGreater(cur);
if (less * 2 < greater)
{
cout << "最长路径超过最短路径两倍" << endl;
return false;
}
if (cur->_col == RED && cur->_parent && cur->_parent->_col == RED)
{
cout << "出现连续红色节点" << endl;
return false; // 检查连续的红色节点
}
if (cur->_col == BLACK)
{
k++;
}
// 递归验证左右子树
return _IsRBTree(cur->_left, k, blackCount) && _IsRBTree(cur->_right, k, blackCount);
}
#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
#include
#include
#include
enum Colour
{
RED,
BLACK
};
template <class K, class V>
struct RBTreeNode
{
pair<K, V> _kv;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode(pair<K, V> kv)
:_kv(kv)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
template <class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
bool Insert(const pair<K, V>& kv);
bool IsRBTree();
void Inorder() { _Inorder(_root); }
void Leorder() { _Leorder(_root); }
private:
void RotateL(Node* root);
void RotateR(Node* root);
int _HeightGreater(Node* root);
int _HeightLess(Node* root);
bool _IsRBTree(Node* root, int k, int blackCount);
void _Inorder(Node* root);
void _Leorder(Node* root);
private:
Node* _root = nullptr;
};
template <class K, class V>
bool RBTree<K, V>::Insert(const pair<K, V>& kv)
{
// 以搜索二叉树的规则插入
if (_root == nullptr)
{
_root = new Node(kv);
// 根节点为黑色
_root->_col = BLACK;
return true;
}
Node* cur = _root;
Node* parent = nullptr;
// 找合适的插入位置
while (cur)
{
if (kv.first < cur->_kv.first)
{
parent = cur;
cur = cur->_left;
}
else if (kv.first > cur->_kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
cur = new Node(kv);
// 判断该插入parent的哪边
if (kv.first < parent->_kv.first)
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
// 插入结束
// 保持平衡
while (parent && parent->_col == RED) // 出现连续的红节点
{
Node* grandParent = parent->_parent;
assert(grandParent);
if (grandParent->_left == parent) // parent在祖父节点左边
{
Node* uncle = grandParent->_right;
// u为红色,一定要提前判断u是否存在
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
grandParent->_col = BLACK;
return true;
}
else // grandParent不是根节点,但其父节点为黑色,也插入完成
{
if (grandParent->_parent && grandParent->_parent->_col == BLACK)
{
return true;
}
else // grandParent的父节点为红,出现连续红节点,更新节点,继续调整
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
// cur在p的左边
if (cur == parent->_left)
{
RotateR(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateL(parent);
RotateR(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return true;
}
} // end of - if (grandParent->_left == parent)
else // p在grandParent的右边
{
Node* uncle = grandParent->_left;
assert(grandParent);
// u为红色
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
_root->_col = BLACK;
return true;
}
else
{
if (grandParent->_parent->_col == BLACK)
{
return true;
}
// 更新继续调整
else
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
// cur在p的右边
if (cur == parent->_right)
{
RotateL(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateR(parent);
RotateL(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return true;
}
} // end of - else
}// end if - while
return true;
}
template <class K, class V>
void RBTree<K, V>::RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
subR->_left = parent;
parent->_right = subRL;
Node* pparent = parent->_parent;
parent->_parent = subR;
if (subRL)
subRL->_parent = parent;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else // 该子树是树的一部分
{
subR->_parent = pparent;
if (subR->_kv.first < pparent->_kv.first)
{
pparent->_left = subR;
}
else
{
pparent->_right = subR;
}
}
}
template <class K, class V>
void RBTree<K, V>::RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
subL->_right = parent;
parent->_left = subLR;
Node* pparent = parent->_parent;
parent->_parent = subL;
if (subLR)
subLR->_parent = parent;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
subL->_parent = pparent;
if (subL->_kv.first < pparent->_kv.first)
{
pparent->_left = subL;
}
else
{
pparent->_right = subL;
}
}
}
template <class K, class V>
int RBTree<K, V>::_HeightGreater(Node* root)
{
if (root == nullptr)
{
return 0;
}
int leftH = _HeightGreater(root->_left);
int rightH = _HeightGreater(root->_right);
return leftH > rightH ? 1 + leftH : 1 + rightH;
}
template <class K, class V>
int RBTree<K, V>::_HeightLess(Node* root)
{
if (root == nullptr)
{
return 0;
}
int leftH = _HeightLess(root->_left);
int rightH = _HeightLess(root->_right);
return leftH < rightH ? 1 + leftH : 1 + rightH;
}
template <class K, class V>
bool RBTree<K, V>::IsRBTree()
{
int blackCount = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
blackCount++;
}
cur = cur->_left;
}
int k = 0;
return _IsRBTree(_root, k, blackCount);
}
template <class K, class V>
bool RBTree<K, V>::_IsRBTree(Node* cur, int k, int blackCount)
{
if (cur == nullptr)
{
if (blackCount != k)
{
cout << "路径上的黑色节点数量不相等" << endl;
return false;
}
return true;
}
if (_root->_col != BLACK)
{
cout << "根节点为红色" << endl;
return false;
}
// 求以cur为根节点的最小高度与最大高度
int less = _HeightLess(cur);
int greater = _HeightGreater(cur);
if (less * 2 < greater)
{
cout << "最长路径超过最短路径两倍" << endl;
return false;
}
if (cur->_col == RED && cur->_parent && cur->_parent->_col == RED)
{
cout << "出现连续红色节点" << endl;
return false; // 检查连续的红色节点
}
if (cur->_col == BLACK)
{
k++;
}
// 递归验证左右子树
return _IsRBTree(cur->_left, k, blackCount) && _IsRBTree(cur->_right, k, blackCount);
}
template <class K, class V>
void RBTree<K, V>::_Inorder(Node* root)
{
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->_kv.first << ' ';
_Inorder(root->_right);
}
template <class K, class V>
void RBTree<K, V>::_Leorder(Node* root)
{
queue<Node*> q;
q.push(root);
int count = 1;
while (!q.empty())
{
while (count)
{
Node* top = q.front();
q.pop();
count--;
if (top)
{
q.push(top->_left);
q.push(top->_right);
cout << top->_col << ' ';
}
else
{
cout << "nullptr ";
}
}
count = q.size();
cout << endl;
}
}