#ifndef _RB_TREE_
#define _RB_TREE_
#include <iostream>
#include <assert.h>
using namespace std;
void TestRBTree();
/*
性质:
1.每个节点要么是红色的,要么是黑色的
2.根节点是黑色的
3.每个叶节点是黑色的
4.如果节点是红色的,则它的两个子节点都必须是黑色的
5.对于每个节点,从该节点到其子孙节点的所有路径上包含相同数目的黑色节点
实现RBTree的关键点:
1.数据结构
2.左、右旋转:对照着伪代码,好实现
3.插入:对照着伪代码,好实现,但是理解起来,不太好理解,
4.删除:知其然,知其所以然
*/
enum Color
{
Red,
Black
};
// 节点数据结构
struct RBTreeNode
{
int key;
Color color;
RBTreeNode *left;
RBTreeNode *right;
RBTreeNode *parent; //
bool operator==(const RBTreeNode lhs)
{
return (key == lhs.key);
}
};
/*
旋转好实现,关键是识别出在哪里旋转,怎么旋转
树的旋转:修改树中某些节点的颜色以及指针,使之符合定义
左旋转:
对某一个节点A实施左旋转:最大的右子结点B成为父节点,B的左子树成为
A的右子树,A成为B的左子树
右旋转:
对某一个节点A实施右旋转:最大的左子节点B成为父节点,B的右子树成为
A的左子树,A成为B的右子树
*/
/*
节点插入:
1.找到插入点
2.插入节点,并设为RED
3.调整树结构
插入节点只会破坏2、4:因为插入默认的都是Red
1.插入的是根节点
2.插入的父节点是Black:OK
3.当前节点的父节点是红色且叔叔节点也是红色:case1
将当前节点的父节点和叔叔节点变为:black
祖父节点变为:Red
并将当前节点调整到祖父节点处
4.当前节点的父亲节点是红色、叔叔节点时黑色、当前节点是右子树 :case2
将当前节点的父节点作为当前节点,并左旋
5.当前节点的父亲节点是红色、叔叔节点时黑色、当前节点是左子树 :case3
当前节点的父节点变为:Black
当前节点的祖父节点变为:Red
对当前节点的祖父节点右旋
case2先执行4到达case3,通过调整后满足要求
case2->leftRotate->case3->rightRotate
*/
/*
节点删除:
如果删除的是Red,不用调整
否则,需要调整
1.当前节点是红色:
直接染成黑色
2.当前节点时黑色且是根节点
结束
3.当前节点时左子树,且当前节点为Black,兄弟节点是:Red
父节点变为:Red
兄弟节点变为:Black
左旋:父亲节点
4.当前节点为左子树,且当前节点为Black,兄弟节点:Black,且兄弟的两个孩子都是Black
将兄弟节点变为:Red
将当前节点置为父节点
5.当前节点为左子树,且当前节点为Black,兄弟节点是Black,兄弟节点的右子树为Black,左子树为Red
将兄弟节点的左子树置为Black
兄弟节点置为Red
右旋兄弟节点
6.当前节点为左子树,且当前节点为Black,兄弟节点是Black,兄弟节点的右子树为Red,左子树任意
将兄弟节点的颜色置为当前节点的父节点颜色
将当前节点父节点的颜色置为:Black
兄弟节点的右子树置为:Black
左旋当前节点的父节点
*/
// 左旋转
/*
左旋转:
对某一个节点A实施左旋转:最大的右子结点B成为父节点,B的左子树成为
A的右子树,A成为B的左子树
*/
// 对node节点进行左旋转
void LeftRotate(RBTreeNode * &root, RBTreeNode *node);
// 右旋转
/*
右旋转:
对某一个节点A实施右旋转:最大的左子节点B成为父节点,B的右子树成为
A的左子树,A成为B的右子树
*/
void RightRotate(RBTreeNode * &root, RBTreeNode *node);
// 节点插入
void InsertNode(RBTreeNode * &root, RBTreeNode *node);
// 插入调整
void RBTreeInsertFixUp(RBTreeNode * &root, RBTreeNode *node);
// 删除节点
RBTreeNode* DeleteNode(RBTreeNode * &root, RBTreeNode *node);
// 得到一个节点的中序遍历的后继节点
RBTreeNode *Successor(RBTreeNode *node);
// 得到最小节点
RBTreeNode *Minimum(RBTreeNode *root);
void RBTreeDeleteFixUp(RBTreeNode * &root, RBTreeNode *node);
#endif
#include "3_RBTree.h"
void TestRBTree()
{
cout << "Test RBTree" << endl;
}
// 对某一个节点A实施左旋转:最大的右子结点B成为父节点,B的左子树成为
// A的右子树,A成为B的左子树
void LeftRotate(RBTreeNode * &root, RBTreeNode *node)
{
// 假定node的右子节点不为空
assert(node->right);
RBTreeNode *right = node->right;
// right的左子树成为node的右子树
node->right = right->left;
right->left->parent = node;
// 设置right的父节点
right->parent = node->parent;
// 如果原来right为root
if (right->parent == NULL)
{
root = right;
}
else
{
if (node == node->parent->left)
{
node->parent->left = right;
}
else
{
node->parent->right = right;
}
}
// 将right设置为node的左子节点
node->parent = right;
right->left = node;
}
// 对某一个节点A实施右旋转:最大的左子节点B成为父节点,B的右子树成为
// A的左子树,A成为B的右子树
void RightRotate(RBTreeNode * &root, RBTreeNode *a)
{
RBTreeNode *b = a->left;
assert(b);
// 将b的右子树设为a的左子树
a->left = b->right;
b->right->parent = a;
// 设置b的parent
b->parent = a->parent;
// a为root
if (a->parent == NULL)
{
root = b;
}
else
{
if (a->parent->left == a)
{
a->parent->left = b;
}
else
{
a->parent->right = b;
}
}
// a成为b的右子树
b->right = a;
a->parent = b;
}
/*
节点插入:
1.找到插入点
2.插入节点,并设为RED
3.调整树结构
*/
void InsertNode(RBTreeNode * &root, RBTreeNode *node)
{
// 找到插入点
assert(node);
RBTreeNode *x = root;
RBTreeNode *y = NULL;
while (x)
{
y = x;
if (x->key < node->key)
{
x = x->left;
}
else
{
x = x->right;
}
}
node->parent = y;
// 如果y为空,说明root为空
if (y == NULL)
{
root = node;
}
else if (y->key < node->key)
{
y->right = node;
}
else
{
y->left = node;
}
node->left = NULL;
node->right = NULL;
node->color = Color::Red;
RBTreeInsertFixUp(root, node);
}
/*
插入节点只会破坏2、4:因为插入默认的都是Red
1.插入的是根节点
2.插入的父节点是Black:OK
3.当前节点的父节点是红色且叔叔节点也是红色:case1
将当前节点的父节点和叔叔节点变为:black
祖父节点变为:Red
并将当前节点调整到祖父节点处
4.当前节点的父亲节点是红色、叔叔节点时黑色、当前节点是右子树 :case2
将当前节点的父节点作为当前节点,并左旋
5.当前节点的父亲节点是红色、叔叔节点时黑色、当前节点是左子树 :case3
当前节点的父节点变为:Black
当前节点的祖父节点变为:Red
对当前节点的祖父节点右旋
case2先执行4到达case3,通过调整后满足要求
case2->leftRotate->case3->rightRotate
*/
void RBTreeInsertFixUp(RBTreeNode * &root, RBTreeNode *node)
{
while (node->parent->color == Color::Red)
{
// 左子节点
if (node->parent == node->parent->parent->left)
{
// 叔叔节点
RBTreeNode *y = node->parent->parent->right;
if (y->color == Color::Red) // case 1
{
node->parent->color = Color::Black;
y->color = Color::Black;
node->parent->parent->color = Color::Red;
node = node->parent->parent;
} // 如果node是右子结点
else if (node == node->parent->right) // case 2
{
node = node->parent;
LeftRotate(root, node);
}
node->parent->color = Color::Black;
node->parent->parent->color = Color::Red;
RightRotate(root, node->parent->parent);
}
// 右子节点
else
{
// 叔叔节点
RBTreeNode *y = node->parent->parent->left;
if (y->color == Color::Red) // case 1
{
node->parent->color = Color::Black;
y->color = Color::Black;
node->parent->parent->color = Color::Red;
node = node->parent->parent;
} // 如果node是右子结点
else if (node == node->parent->left) // case 2
{
node = node->parent;
RightRotate(root, node);
}
node->parent->color = Color::Black;
node->parent->parent->color = Color::Red;
LeftRotate(root, node->parent->parent);
}
}
root->color = Color::Black;
}
RBTreeNode* DeleteNode(RBTreeNode * &root, RBTreeNode *node)
{
// 172 12.3 155?
RBTreeNode *y = NULL;
if ((node->left == NULL) || (node->right == NULL))
{
y = node;
}
else
{
y = Successor(node);
}
RBTreeNode *x = NULL;
if (y->left)
{
x = y->left;
}
else
{
x = y->right;
}
x->parent = y->parent;
if (y->parent == NULL)
{
root = x;
}
else
{
if (y == y->parent->left)
{
y->parent->left = x;
}
else
{
y->parent->right = x;
}
}
if (!(y == node))
{
node->key = y->key;
node->color = y->color;
node->left = y->left;
node->right = y->right;
node->parent = y->parent;
}
if (y->color == Color::Black)
{
RBTreeDeleteFixUp(root, x);
}
return y;
}
/*
节点删除:
如果删除的是Red,不用调整
否则,需要调整
1.当前节点是红色:
直接染成黑色
2.当前节点时黑色且是根节点
结束
3.当前节点时左子树,且当前节点为Black,兄弟节点是:Red
父节点变为:Red
兄弟节点变为:Black
左旋:父亲节点
4.当前节点为左子树,且当前节点为Black,兄弟节点:Black,且兄弟的两个孩子都是Black
将兄弟节点变为:Red
将当前节点置为父节点
5.当前节点为左子树,且当前节点为Black,兄弟节点是Black,兄弟节点的右子树为Black,左子树为Red
将兄弟节点的左子树置为Black
兄弟节点置为Red
右旋兄弟节点
6.当前节点为左子树,且当前节点为Black,兄弟节点是Black,兄弟节点的右子树为Red,左子树任意
将兄弟节点的颜色置为当前节点的父节点颜色
将当前节点父节点的颜色置为:Black
兄弟节点的右子树置为:Black
左旋当前节点的父节点
*/
void RBTreeDeleteFixUp(RBTreeNode * &root, RBTreeNode *x)
{
while (x != root && x->color == Color::Black)
{
// x为左子节点
if (x == x->parent->left)
{
// w为其兄弟节点
RBTreeNode *w = x->parent->right;
if (w->color == Color::Red)
{
x->parent->color = Color::Red;
w->color = Color::Black;
LeftRotate(root, x->parent);
}
if (w->left->color == Color::Black &&
w->right->color == Color::Black)
{
w->color = Color::Red;
x = x->parent;
}
else if (w->right->color == Color::Black)
{
w->left->color = Color::Black;
w->color = Color::Red;
RightRotate(root, w);
w = x->parent->right;
}
w->color = x->parent->color;
x->parent->color = Color::Black;
w->right->color = Color::Black;
LeftRotate(root, x->parent);
x = root;
}
else
{
// w为其兄弟节点
RBTreeNode *w = x->parent->left;
if (w->color == Color::Red)
{
x->parent->color = Color::Red;
w->color = Color::Black;
RightRotate(root, x->parent);
}
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;
LeftRotate(root, w);
w = x->parent->left;
}
w->color = x->parent->color;
x->parent->color = Color::Black;
w->left->color = Color::Black;
RightRotate(root, x->parent);
x = root;
}
}
}
RBTreeNode *Successor(RBTreeNode *node)
{
if (node->right)
{
return Minimum(node);
}
RBTreeNode *y = node->parent;
// 找到第一个node不是其右子节点,而是其子节点的节点
while (y && (node == y->right))
{
node = y;
y = y->parent;
}
return y;
}
RBTreeNode *Minimum(RBTreeNode *root)
{
while (root->left)
{
root = root->left;
}
return root;
}