Files
Data-Structure/BinaryTree/BalanceTree/Red-Black Tree/RBTree.h
2025-08-25 16:26:11 +08:00

371 lines
9.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#pragma once
#include <iostream>
#include "TreeNode.h"
template <class T>
class RBTree {
private:
TreeNode<T>* root;
TreeNode<T>* nul;
int size;
void initNul() {
nul = new TreeNode<T>(0, nul, nul, nul);
nul->color = Color::RED;
}
void inorder(TreeNode<T>* x);
void dispose(TreeNode<T>* x) {
if (x == nullptr || x == nul) return;
dispose(x->left);
dispose(x->right);
delete x;
//重点不能delete nul作为全局的哨兵
}
public:
RBTree() : size(0) { initNul(); root = nul; }
RBTree(TreeNode<T>* r, int s) : root(r), size(s) { initNul(); }
~RBTree() {
dispose(root);
root = nullptr;
delete nul;
//删除哨兵,需要删除
}
TreeNode<T>* RotateLeft(TreeNode<T>* x);//RR
TreeNode<T>* RotateRight(TreeNode<T>* x);//LL
void insert(const T& e);
void fixinsert(TreeNode<T>* x);
void fixdelete(TreeNode<T>* x);
void inorder() { inorder(root); }
void erase(const T& e);
TreeNode<T>* find(const T& e);
};
template<class T>
inline TreeNode<T>* RBTree<T>::RotateLeft(TreeNode<T>* x) {
TreeNode<T>* y = x->right; // 右孩子
TreeNode<T>* T2 = y->left; // y 的左子树暂存
// 左旋
y->left = x;
x->right = T2;
// 更新 parent 指针
if (T2) T2->parent = x; // 如果 T2 存在
y->parent = x->parent; // y 接上 x 的父节点
if (x->parent == nul) { // x 是根节点
root = y;
}
else if (x == x->parent->left) {
x->parent->left = y;
}
else {
x->parent->right = y;
}
x->parent = y;
return y; // 返回新子树根
}
template<class T>
TreeNode<T>* RBTree<T>::RotateRight(TreeNode<T>* x) {
//有parent不需要递归直接修改parent
TreeNode<T>* y = x->left;
TreeNode<T>* T2 = y->right;
// 旋转
y->right = x;
x->left = T2;
// 更新 parent 指针
if (T2) T2->parent = x; // 如果 T2 存在
y->parent = x->parent; // y 接上 x 的父节点
if (x->parent == nul) { // x 是根节点
root = y;
}
else if (x == x->parent->left) {
x->parent->left = y;
}
else {
x->parent->right = y;
}
x->parent = y;
return y; // 返回新子树根
}
template<class T>
inline void RBTree<T>::inorder(TreeNode<T>* x)
{
if (x == nul) return;
inorder(x->left);
std::cout << x->element << " ";
inorder(x->right);
}
template<class T>
inline void RBTree<T>::insert(const T& e)
{
TreeNode<T>* p = new TreeNode<T>(e, nul, nul, nul);
TreeNode<T>* current = root;
TreeNode<T>* parent = nul;
//BST插入有parent就不需要递归节点了
while (current != nul) {
parent = current;
if (e < parent->element) current = parent->left;
else current = parent->right;
}
p->parent = parent;
if (parent == nul) root = p;
if (parent == nul) root = p;
else if (e < parent->element) parent->left = p;
else parent->right = p;
//FixInsert
fixinsert(p);
}
template<class T>
inline void RBTree<T>::fixinsert(TreeNode<T>* x)
{
while (x != root && x->parent->color == Color::RED) {
//看叔叔
if (x->parent->parent->left == x->parent) {
//左节点
if (x->parent->parent->right->color == Color::RED) {
//叔叔红
x->parent->color = x->parent->parent->right->color = Color::BLACK;
x->parent->parent->color = Color::RED;
//fixinsert(x->parent->parent);递归不好,容易重复判断,不易处理根节点颜色
x = x->parent->parent;
continue;
}
if (x == x->parent->left) {
//LL//先变色祖父,父亲
x->parent->parent->color = Color::RED;
x->parent->color = Color::BLACK;
//再右旋
RotateRight(x->parent->parent);
}
//LR
if (x == x->parent->right) {
//变成LL
x = x->parent;
RotateLeft(x);
//不需要再LL了下一个循环自动变成LL
}
}
//else对称情况父亲为右节点
else {
//1-叔叔红
if (x->parent->parent->left->color == Color::RED) {
x->parent->parent->left->color = Color::BLACK;
x->parent->color = Color::BLACK;
x->parent->parent->color = Color::RED;
x = x->parent->parent;
}
//2-叔叔黑
else {
//2-1-RL -> 调整为RR再做下一步操作
if (x == x->parent->left) {
x = x->parent;
RotateRight(x);
}
//3-RR接着上面的2-1
x->parent->color = Color::BLACK;
x->parent->parent->color = Color::RED;
RotateLeft(x->parent->parent);
}
}
}
root->color = Color::BLACK;
}
// x 表示被删除节点的替代节点(可能是 nul 哨兵)
// 只有当被删节点或替代节点是黑色时,才需要进入 fixdelete
template<class T>
void RBTree<T>::fixdelete(TreeNode<T>* x) {
while (x != root && x->color == Color::BLACK) {
// 情况1x 是左孩子
if (x == x->parent->left) {
TreeNode<T>* w = x->parent->right; // x 的兄弟节点
// case 1: 兄弟是红色
// -> 把兄弟染黑,父亲染红,然后左旋
// -> 转化为兄弟是黑色的情况
if (w->color == Color::RED) {
w->color = Color::BLACK;
x->parent->color = Color::RED;
RotateLeft(x->parent);
w = x->parent->right; // 更新兄弟
}
// case 2: 兄弟是黑色并且两个侄子w->left, w->right都是黑色
// -> 把兄弟染红,相当于把 "多余的黑色" 往上传递
// -> 修复过程继续向上进行
if (w->left->color == Color::BLACK && w->right->color == Color::BLACK) {
w->color = Color::RED;
x = x->parent; // 往上修复
}
else {
// case 3: 兄弟是黑色,且兄弟的右孩子是黑色,左孩子是红色
// -> 先把兄弟染红,左孩子染黑,然后右旋兄弟
// -> 转化为 case 4
if (w->right->color == Color::BLACK) {
w->left->color = Color::BLACK;
w->color = Color::RED;
RotateRight(w);
w = x->parent->right; // 更新兄弟
}
// case 4: 兄弟是黑色,且兄弟的右孩子是红色
// -> 用兄弟替换父亲颜色,父亲染黑,兄弟的右孩子染黑
// -> 左旋父亲,修复完成,直接退出循环
w->color = x->parent->color;
x->parent->color = Color::BLACK;
w->right->color = Color::BLACK;
RotateLeft(x->parent);
x = root; // 结束循环
}
}
// 情况2x 是右孩子(对称情况)
else {
TreeNode<T>* w = x->parent->left;
if (w->color == Color::RED) {
w->color = Color::BLACK;
x->parent->color = Color::RED;
RotateRight(x->parent);
w = x->parent->left;
}
if (w->right->color == Color::BLACK && w->left->color == Color::BLACK) {
w->color = Color::RED;
x = x->parent;
}
else {
if (w->left->color == Color::BLACK) {
w->right->color = Color::BLACK;
w->color = Color::RED;
RotateLeft(w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = Color::BLACK;
w->left->color = Color::BLACK;
RotateRight(x->parent);
x = root;
}
}
}
// 最后保证 x 是黑色(可能是根或者 nul
x->color = Color::BLACK;
}
template<class T>
inline void RBTree<T>::erase(const T& e)
{
TreeNode<T>* z = find(e);
//1-BST删除重置找本节点右树最小或者左树最大
TreeNode<T>* y = z; // 实际要删除的节点(可能是 z也可能是 z 的后继)
TreeNode<T>* x; // y 的替代节点(可能是子节点,也可能是 nul
Color yOriginalColor = y->color; // 记录 y 的原始颜色,决定是否需要 fixdelete
// case 1: z 没有左子树 -> 用右子树替代 z
if (z->left == nul) {
x = z->right; // 替代节点
// 把 z 从父亲断开
if (z->parent == nul) root = x;
else if (z == z->parent->left) z->parent->left = x;
else z->parent->right = x;
x->parent = z->parent;
}
// case 2: z 没有右子树 -> 用左子树替代 z
else if (z->right == nul) {
x = z->left;
if (z->parent == nul) root = x;
else if (z == z->parent->left) z->parent->left = x;
else z->parent->right = x;
x->parent = z->parent;
}
// case 3: z 左右孩子都有 -> 找到 z 的中序后继
else {
// 找 z 的后继(右子树最左节点)
y = z->right;
while (y->left != nul) y = y->left;
yOriginalColor = y->color; // 记录后继的颜色
x = (y->right != nul ? y->right : nul); // 后继的右孩子作为替代
// 如果 y 不是 z 的直接右孩子
if (y->parent != z) {
// 把 y->right 替代 y
if (y->parent->left == y) y->parent->left = x;
else y->parent->right = x;
x->parent = y->parent;
// 把 z->right 挂到 y 的右子树
y->right = z->right;
y->right->parent = y;
}
// 把 z->left 挂到 y 的左子树
if (z->parent == nul) root = y;
else if (z == z->parent->left) z->parent->left = y;
else z->parent->right = y;
y->parent = z->parent;
y->left = z->left;
y->left->parent = y;
y->color = z->color;
}
delete z;
//2-RBT性质重置
// 如果删除的实际节点是黑色,可能破坏红黑树性质 → fixdelete
if (yOriginalColor == Color::BLACK) {
fixdelete(x);
}
}
template<class T>
inline TreeNode<T>* RBTree<T>::find(const T& e)
{
TreeNode<T>* p = root;
while (p != nul) {
if (e < p->element) p = p->left;
else if (e > p->element) p = p->right;
else break;
}
if (!p) p = nul;
return p;
}
/*
推荐写法
if (x->parent == x->parent->parent->left) { // 父在左
TreeNode<T>* y = x->parent->parent->right; // 叔叔
if (y->color == Color::RED) { // Case 1: 叔红
x->parent->color = Color::BLACK;
y->color = Color::BLACK;
x->parent->parent->color = Color::RED;
x = x->parent->parent; // 上移祖父
} else {
if (x == x->parent->right) { // Case 2: LR
x = x->parent;
RotateLeft(x);
}
// Case 3: LL
x->parent->color = Color::BLACK;
x->parent->parent->color = Color::RED;
RotateRight(x->parent->parent);
}
按照顺序写这里可以看else父亲为右节点的思路
*/