#include <iostream>
#include <iomanip>
using namespace std;
template<class T>
class RBTree{
//红黑树,最坏情形O(logN),图示见 https://www.cnblogs.com/skywang12345/p/3245399.html
//满足下面性质的二分查找树
//(0.nullptr节点视为黑色)
//1.节点是红色或黑色
//2.整棵树的根是黑色
//3.如果一个节点是红色,子节点必须是黑色
//4.从一个节点到一个nullptr指针的每一条路径必须包含相同数目的黑色节点
//红黑树的高度最多是2log(N+1),保证查找是对数操作
#define rb_parent(r) ((r)->parent)
#define rb_color(r) ((r)->color)
#define rb_is_red(r) ((r)->color==RED)
#define rb_is_black(r) ((r)->color==BLACK)
#define rb_set_black(r) do { (r)->color = BLACK; } while (0)
#define rb_set_red(r) do { (r)->color = RED; } while (0)
#define rb_set_parent(r,p) do { (r)->parent = (p); } while (0)
#define rb_set_color(r,c) do { (r)->color = (c); } while (0)
private:
enum RBTColor{RED,BLACK};
struct RBTNode{
RBTColor color;
T data;
RBTNode* left;
RBTNode* right;
RBTNode* parent;
RBTNode(T v,RBTColor c,RBTNode* l,RBTNode* r,RBTNode* p):data(v),left(l),right(r),parent(p),color(c){};
};
RBTNode* root;
void inOrderTraversal(RBTNode* node){
if (!node) return;
inOrderTraversal(node->left);
cout << node->data << ' ';
inOrderTraversal(node->right);
}
void print(RBTNode* tree,T v,int direction){
if (tree){
if (direction==0) cout << setw(2) << tree->data << "(B) is root" << endl;
else cout << setw(2) << tree->data << (rb_is_red(tree)?"(R)":"(B)") << " is " << setw(2) << v << "'s " << setw(12) << (direction==1?"right child" : "left child") << endl;
}
if (tree->left) print(tree->left,tree->data,-1);
if (tree->right) print(tree->right,tree->data, 1);
}
//插入叶子节点应该是红色,因为如果是黑色就会违背性质4
//下面如果其父节点是黑色可以直接结束,如果是红色必须调整树使其满足性质3
//上面链接中的原文分析得很精彩,不懂why可以去看
//对x进行左旋=>x的右子节点代替x,x成为其左子节点
//对x进行右旋=>x的左子节点代替x,x成为其右子节点
void leftRotate(RBTNode* &root, RBTNode* x){
// 设置x的右孩子为y
RBTNode *y = x->right;
// 将 “y的左孩子” 设为 “x的右孩子”;
// 如果y的左孩子非空,将 “x” 设为 “y的左孩子的父亲”
x->right = y->left;
if (y->left) y->left->parent = x;
// 将 “x的父亲” 设为 “y的父亲”
y->parent = x->parent;
if (!x->parent) root = y; // 如果 “x的父亲” 是空节点,则将y设为根节点
else{
if (x->parent->left == x) x->parent->left = y; // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
else x->parent->right = y; // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
}
// 将 “x” 设为 “y的左孩子”
y->left = x;
// 将 “x的父节点” 设为 “y”
x->parent = y;
}
/*
* 对红黑树的节点(y)进行右旋转
*
* 右旋示意图(对节点y进行左旋):
* py py
* / /
* y x
* / \ --(右旋)--> / \ #
* x ry lx y
* / \ / \ #
* lx rx rx ry
*
*/
void rightRotate(RBTNode* &root, RBTNode* y){
// 设置x是当前节点的左孩子。
RBTNode *x = y->left;
// 将 “x的右孩子” 设为 “y的左孩子”;
// 如果"x的右孩子"不为空的话,将 “y” 设为 “x的右孩子的父亲”
y->left = x->right;
if (x->right) x->right->parent = y;
// 将 “y的父亲” 设为 “x的父亲”
x->parent = y->parent;
if (!y->parent) root = x; // 如果 “y的父亲” 是空节点,则将x设为根节点
else{
if (y == y->parent->right) y->parent->right = x; // 如果 y是它父节点的右孩子,则将x设为“y的父节点的右孩子”
else y->parent->left = x; // (y是它父节点的左孩子) 将x设为“x的父节点的左孩子”
}
// 将 “y” 设为 “x的右孩子”
x->right = y;
// 将 “y的父节点” 设为 “x”
y->parent = x;
}
//插入的叶子结点(当前节点)是红色,父节点也是红色可分为下面三种情况:
//1.叔叔节点(父亲的兄弟节点)也是红色:父变黑.叔变黑,祖父变红,将祖父设为当前节点
//2.叔叔节点(父亲的兄弟节点)是黑色,且待插入节点是挂在了右边:将父节点设为当前节点,当前节点左旋(这样插入的节点代替了原来的父节点)
//3.叔叔节点(父亲的兄弟节点)是黑色,且待插入节点是挂在了左边:父变黑,祖父变红,祖父节点右旋
void insert(RBTNode* &root,RBTNode* node){
RBTNode* parent=nullptr;
RBTNode* cur=root;
while (cur){
parent=cur; //保存路径的上一个顶点,找到要插入的位置的父节点
if (node->data<cur->data) cur=cur->left;
else cur=cur->right;
}
node->parent=parent;
if (parent){
if (node->data<parent->data) parent->left=node;
else parent->right=node;
}
else root=node;
node->color=RED;
insertAdjust(root,node); //调整成红黑树
}
void insertAdjust(RBTNode* &root,RBTNode* node){
RBTNode* parent,*gparent;
while ((parent=rb_parent(node)) && rb_is_red(parent)){
//父节点存在且是红色
gparent=rb_parent(parent);
if (parent==gparent->left){
RBTNode* uncle=gparent->right;
if (uncle && rb_is_red(uncle)){
//情况1
rb_set_black(parent);
rb_set_black(uncle);
rb_set_red(gparent);
node=gparent;
}
else if (parent->right==node){
//情况2
leftRotate(root,parent);
RBTNode* tmp=parent;
parent=node;
node=tmp;
}
//情况3
rb_set_black(parent);
rb_set_red(gparent);
rightRotate(root,gparent);
}
else{
RBTNode* uncle = gparent->left;
if (uncle && rb_is_red(uncle)){
if (uncle && rb_is_red(uncle)){
//情况1
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
else if (parent->left == node){
//情况2
RBTNode* tmp;
rightRotate(root, parent);
tmp = parent;
parent = node;
node = tmp;
}
//情况3
rb_set_black(parent);
rb_set_red(gparent);
leftRotate(root, gparent);
}
}
rb_set_black(root);
}
RBTNode* search(RBTNode* x, T v) const{
if (!x || x->data==v) return x;
if (v < x->data) return search(x->left, v);
else return search(x->right, v);
}
//删除节点(与二叉搜索树操作一样)之后调整成红黑树
void remove(RBTNode* &root, RBTNode *node){
RBTNode *child, *parent;
RBTColor color;
if ((node->left) && (node->right)){
RBTNode *replace = node;
replace = replace->right;
while (replace->left) replace = replace->left; //右子树的最小节点代替
if (rb_parent(node)){
if (rb_parent(node)->left == node) rb_parent(node)->left = replace;
else rb_parent(node)->right = replace;
}
else root = replace;
child = replace->right;
parent = rb_parent(replace);
color = rb_color(replace);
if (parent == node) parent = replace;
else{
if (child) rb_set_parent(child, parent);
parent->left = child;
replace->right = node->right;
rb_set_parent(node->right, replace);
}
replace->parent = node->parent;
replace->color = node->color;
replace->left = node->left;
node->left->parent = replace;
if (color == BLACK) removeAdjust(root, child, parent);
delete node;
return ;
}
if (node->left) child = node->left;
else child = node->right;
parent = node->parent;
color = node->color;
if (child) child->parent = parent;
if (parent){
if (parent->left == node) parent->left = child;
else parent->right = child;
}
else root = child;
if (color == BLACK) removeAdjust(root, child, parent);
delete node;
}
void removeAdjust(RBTNode* &root, RBTNode *node, RBTNode *parent){
RBTNode *other;
while ((!node || rb_is_black(node)) && node != root){
if (parent->left == node){
other = parent->right;
if (rb_is_red(other)){
// Case 1: x的兄弟w是红色的
rb_set_black(other);
rb_set_red(parent);
leftRotate(root, parent);
other = parent->right;
}
if ((!other->left || rb_is_black(other->left)) && (!other->right || rb_is_black(other->right))){
// Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else{
if (!other->right || rb_is_black(other->right)){
// Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
rb_set_black(other->left);
rb_set_red(other);
rightRotate(root, other);
other = parent->right;
}
// Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->right);
leftRotate(root, parent);
node = root;
break;
}
}
else{
other = parent->left;
if (rb_is_red(other)){
// Case 1: x的兄弟w是红色的
rb_set_black(other);
rb_set_red(parent);
rightRotate(root, parent);
other = parent->left;
}
if ((!other->left || rb_is_black(other->left)) && (!other->right || rb_is_black(other->right))){
// Case 2: x的兄弟w是黑色,且w的俩个孩子也都是黑色的
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else{
if (!other->left || rb_is_black(other->left)){
// Case 3: x的兄弟w是黑色的,并且w的左孩子是红色,右孩子为黑色。
rb_set_black(other->right);
rb_set_red(other);
leftRotate(root, other);
other = parent->left;
}
// Case 4: x的兄弟w是黑色的;并且w的右孩子是红色的,左孩子任意颜色。
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->left);
rightRotate(root, parent);
node = root;
break;
}
}
}
if (node) rb_set_black(node);
}
public:
RBTree():root(nullptr){};
void inOrderTraversal(){inOrderTraversal(root);}
void insert(T v){
RBTNode* z=new RBTNode(v,BLACK,nullptr,nullptr,nullptr);
insert(root,z);
}
void remove(T v){
RBTNode* node;
if ((node = search(root, v))) remove(root, node);
}
void print(){
if (root) print(root,root->data,0);
}
};
int main()
{
int a[]= {10, 40, 30, 60, 90, 70, 20, 50, 80};
int check_insert=1; // "插入"动作的检测开关(0,关闭;1,打开)
int check_remove=1; // "删除"动作的检测开关(0,关闭;1,打开)
int i;
int ilen = (sizeof(a)) / (sizeof(a[0])) ;
RBTree<int>* tree=new RBTree<int>();
cout << "== 原始数据: ";
for(i=0; i<ilen; i++)
cout << a[i] <<" ";
cout << endl;
for(i=0; i<ilen; i++)
{
tree->insert(a[i]);
// 设置check_insert=1,测试"添加函数"
if(check_insert)
{
cout << "== 添加节点: " << a[i] << endl;
cout << "== 树的详细信息: " << endl;
tree->print();
cout << endl;
}
}
cout << "\n== 中序遍历: ";
tree->inOrderTraversal();
cout << "== 树的详细信息: " << endl;
tree->print();
// 设置check_remove=1,测试"删除函数"
if(check_remove)
{
for(i=0; i<ilen; i++)
{
tree->remove(a[i]);
cout << "== 删除节点: " << a[i] << endl;
cout << "== 树的详细信息: " << endl;
tree->print();
cout << endl;
}
}
return 0;
}
数据结构与算法分析:红黑树
于 2022-10-03 16:52:50 首次发布