Red-Black-Tree

This commit is contained in:
e2hang
2025-08-25 16:26:11 +08:00
parent 03d0c1b039
commit 74b56aa55c
4 changed files with 670 additions and 0 deletions

View File

@@ -0,0 +1,370 @@
#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;
//<2F>ص㲻<D8B5><E3B2BB>delete nul<75><6C><EFBFBD><EFBFBD>Ϊȫ<CEAA>ֵ<EFBFBD><D6B5>ڱ<EFBFBD><DAB1><EFBFBD>
}
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;
//ɾ<><C9BE><EFBFBD>ڱ<EFBFBD><DAB1><EFBFBD><EFBFBD><EFBFBD>Ҫɾ<D2AA><C9BE>
}
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; // <20>Һ<EFBFBD><D2BA><EFBFBD>
TreeNode<T>* T2 = y->left; // y <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD>
// <20><><EFBFBD><EFBFBD>
y->left = x;
x->right = T2;
// <20><><EFBFBD><EFBFBD> parent ָ<><D6B8>
if (T2) T2->parent = x; // <20><><EFBFBD><EFBFBD> T2 <20><><EFBFBD><EFBFBD>
y->parent = x->parent; // y <20><><EFBFBD><EFBFBD> x <20>ĸ<EFBFBD><C4B8>ڵ<EFBFBD>
if (x->parent == nul) { // x <20>Ǹ<EFBFBD><C7B8>ڵ<EFBFBD>
root = y;
}
else if (x == x->parent->left) {
x->parent->left = y;
}
else {
x->parent->right = y;
}
x->parent = y;
return y; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
template<class T>
TreeNode<T>* RBTree<T>::RotateRight(TreeNode<T>* x) {
//<2F><>parent<6E><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD>ݹ飬ֱ<E9A3AC><D6B1><EFBFBD>޸<EFBFBD>parent
TreeNode<T>* y = x->left;
TreeNode<T>* T2 = y->right;
// <20><>ת
y->right = x;
x->left = T2;
// <20><><EFBFBD><EFBFBD> parent ָ<><D6B8>
if (T2) T2->parent = x; // <20><><EFBFBD><EFBFBD> T2 <20><><EFBFBD><EFBFBD>
y->parent = x->parent; // y <20><><EFBFBD><EFBFBD> x <20>ĸ<EFBFBD><C4B8>ڵ<EFBFBD>
if (x->parent == nul) { // x <20>Ǹ<EFBFBD><C7B8>ڵ<EFBFBD>
root = y;
}
else if (x == x->parent->left) {
x->parent->left = y;
}
else {
x->parent->right = y;
}
x->parent = y;
return y; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
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<53><54><EFBFBD><EFBFBD><EBA3AC>parent<6E>Ͳ<EFBFBD><CDB2><EFBFBD>Ҫ<EFBFBD>ݹ<EFBFBD><DDB9>ڵ<EFBFBD><DAB5><EFBFBD>
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) {
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (x->parent->parent->left == x->parent) {
//<2F><><EFBFBD>ڵ<EFBFBD>
if (x->parent->parent->right->color == Color::RED) {
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
x->parent->color = x->parent->parent->right->color = Color::BLACK;
x->parent->parent->color = Color::RED;
//fixinsert(x->parent->parent);<3B>ݹ鲻<DDB9>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ظ<EFBFBD><D8B8>жϣ<D0B6><CFA3><EFBFBD><EFBFBD>״<EFBFBD><D7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD>ɫ
x = x->parent->parent;
continue;
}
if (x == x->parent->left) {
//LL//<2F>ȱ<EFBFBD>ɫ<EFBFBD><EFBFBD><E6B8B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
x->parent->parent->color = Color::RED;
x->parent->color = Color::BLACK;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RotateRight(x->parent->parent);
}
//LR
if (x == x->parent->right) {
//<2F><><EFBFBD><EFBFBD>LL
x = x->parent;
RotateLeft(x);
//<2F><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>LL<4C>ˣ<EFBFBD><CBA3><EFBFBD>һ<EFBFBD><D2BB>ѭ<EFBFBD><D1AD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>LL
}
}
//else<73>Գ<EFBFBD><D4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ҽڵ<D2BD>
else {
//1-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
else {
//2-1-RL -> <20><><EFBFBD><EFBFBD>ΪRR<52><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (x == x->parent->left) {
x = x->parent;
RotateRight(x);
}
//3-RR<52><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>2-1
x->parent->color = Color::BLACK;
x->parent->parent->color = Color::RED;
RotateLeft(x->parent->parent);
}
}
}
root->color = Color::BLACK;
}
// x <20><>ʾ<EFBFBD><CABE>ɾ<EFBFBD><C9BE><EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㣨<DAB5><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> nul <20>ڱ<EFBFBD><DAB1><EFBFBD>
// ֻ<>е<EFBFBD><D0B5><EFBFBD>ɾ<EFBFBD>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD><DAB5>Ǻ<EFBFBD>ɫʱ<C9AB><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD> fixdelete
template<class T>
void RBTree<T>::fixdelete(TreeNode<T>* x) {
while (x != root && x->color == Color::BLACK) {
// <20><><EFBFBD><EFBFBD>1<EFBFBD><31>x <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (x == x->parent->left) {
TreeNode<T>* w = x->parent->right; // x <20><><EFBFBD>ֵܽڵ<DCBD>
// case 1: <20>ֵ<EFBFBD><D6B5>Ǻ<EFBFBD>ɫ
// -> <20><><EFBFBD>ֵ<EFBFBD>Ⱦ<EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD>죬Ȼ<ECA3AC><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// -> ת<><D7AA>Ϊ<EFBFBD>ֵ<EFBFBD><D6B5>Ǻ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (w->color == Color::RED) {
w->color = Color::BLACK;
x->parent->color = Color::RED;
RotateLeft(x->parent);
w = x->parent->right; // <20><><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>
}
// case 2: <20>ֵ<EFBFBD><D6B5>Ǻ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֶ<EFBFBD>ӣ<EFBFBD>w->left, w->right<68><74><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD>ɫ
// -> <20><><EFBFBD>ֵ<EFBFBD>Ⱦ<EFBFBD><EFBFBD><EFBFBD>ڰ<EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD>ĺ<EFBFBD>ɫ" <20><><EFBFBD>ϴ<EFBFBD><CFB4><EFBFBD>
// -> <20>޸<EFBFBD><DEB8><EFBFBD><EFBFBD>̼<EFBFBD><CCBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ͻ<EFBFBD><CFBD><EFBFBD>
if (w->left->color == Color::BLACK && w->right->color == Color::BLACK) {
w->color = Color::RED;
x = x->parent; // <20><><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>
}
else {
// case 3: <20>ֵ<EFBFBD><D6B5>Ǻ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>ֵܵ<D6B5><DCB5>Һ<EFBFBD><D2BA><EFBFBD><EFBFBD>Ǻ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǻ<EFBFBD>ɫ
// -> <20>Ȱ<EFBFBD><C8B0>ֵ<EFBFBD>Ⱦ<EFBFBD><EFBFBD><ECA3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD>ڣ<EFBFBD>Ȼ<EFBFBD><C8BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>
// -> ת<><D7AA>Ϊ case 4
if (w->right->color == Color::BLACK) {
w->left->color = Color::BLACK;
w->color = Color::RED;
RotateRight(w);
w = x->parent->right; // <20><><EFBFBD><EFBFBD><EFBFBD>ֵ<EFBFBD>
}
// case 4: <20>ֵ<EFBFBD><D6B5>Ǻ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD>ֵܵ<D6B5><DCB5>Һ<EFBFBD><D2BA><EFBFBD><EFBFBD>Ǻ<EFBFBD>ɫ
// -> <20><><EFBFBD>ֵ<EFBFBD><D6B5><EFBFBD><E6BBBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ⱦ<EFBFBD>ڣ<EFBFBD><DAA3>ֵܵ<D6B5><DCB5>Һ<EFBFBD><D2BA><EFBFBD>Ⱦ<EFBFBD><C8BE>
// -> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ף<EFBFBD><D7A3>޸<EFBFBD><DEB8><EFBFBD><EFBFBD>ɣ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD>˳<EFBFBD>ѭ<EFBFBD><D1AD>
w->color = x->parent->color;
x->parent->color = Color::BLACK;
w->right->color = Color::BLACK;
RotateLeft(x->parent);
x = root; // <20><><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
}
}
// <20><><EFBFBD><EFBFBD>2<EFBFBD><32>x <20><><EFBFBD>Һ<EFBFBD><D2BA>ӣ<EFBFBD><D3A3>Գ<EFBFBD><D4B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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;
}
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤ x <20>Ǻ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǹ<EFBFBD><C7B8><EFBFBD><EFBFBD><EFBFBD> nul<75><6C>
x->color = Color::BLACK;
}
template<class T>
inline void RBTree<T>::erase(const T& e)
{
TreeNode<T>* z = find(e);
//1-BSTɾ<54><C9BE><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3>ұ<EFBFBD><D2B1>ڵ<EFBFBD><DAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TreeNode<T>* y = z; // ʵ<><CAB5>Ҫɾ<D2AA><C9BE><EFBFBD>Ľڵ㣨<DAB5><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> z<><7A>Ҳ<EFBFBD><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> z <20>ĺ<EFBFBD><C4BA>̣<EFBFBD>
TreeNode<T>* x; // y <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㣨<DAB5><E3A3A8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӽڵ㣬Ҳ<E3A3AC><D2B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD> nul<75><6C>
Color yOriginalColor = y->color; // <20><>¼ y <20><>ԭʼ<D4AD><CABC>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ fixdelete
// case 1: z û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> z
if (z->left == nul) {
x = z->right; // <20><><EFBFBD><EFBFBD><EFBFBD>ڵ<EFBFBD>
// <20><> z <20>Ӹ<EFBFBD><D3B8>׶Ͽ<D7B6>
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 û<><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 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 <20><><EFBFBD>Һ<EFBFBD><D2BA>Ӷ<EFBFBD><D3B6><EFBFBD> -> <20>ҵ<EFBFBD> z <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
else {
// <20><> z <20>ĺ<EFBFBD><C4BA>̣<EFBFBD><CCA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڵ㣩
y = z->right;
while (y->left != nul) y = y->left;
yOriginalColor = y->color; // <20><>¼<EFBFBD><C2BC><EFBFBD>̵<EFBFBD><CCB5><EFBFBD>ɫ
x = (y->right != nul ? y->right : nul); // <20><><EFBFBD>̵<EFBFBD><CCB5>Һ<EFBFBD><D2BA><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> y <20><><EFBFBD><EFBFBD> z <20><>ֱ<EFBFBD><D6B1><EFBFBD>Һ<EFBFBD><D2BA><EFBFBD>
if (y->parent != z) {
// <20><> y->right <20><><EFBFBD><EFBFBD> y
if (y->parent->left == y) y->parent->left = x;
else y->parent->right = x;
x->parent = y->parent;
// <20><> z->right <20>ҵ<EFBFBD> y <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
y->right = z->right;
y->right->parent = y;
}
// <20><> z->left <20>ҵ<EFBFBD> y <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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<42><54><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD>ʵ<EFBFBD>ʽڵ<CABD><DAB5>Ǻ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƻ<EFBFBD><C6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 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;
}
/*
<EFBFBD>Ƽ<EFBFBD>д<EFBFBD><EFBFBD>
if (x->parent == x->parent->parent->left) { // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TreeNode<T>* y = x->parent->parent->right; // <20><><EFBFBD><EFBFBD>
if (y->color == Color::RED) { // Case 1: <20><><EFBFBD><EFBFBD>
x->parent->color = Color::BLACK;
y->color = Color::BLACK;
x->parent->parent->color = Color::RED;
x = x->parent->parent; // <20><><EFBFBD><EFBFBD><EFBFBD>
} 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);
}
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD><EFBFBD>д<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Կ<EFBFBD>else<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ҽڵ㣩<EFBFBD><EFBFBD>˼·
*/