性质:
插入:
旋转:
删除:
情况2.2的删除:
1. 兄弟是黑色,兄弟的右孩子是红色。
2. 兄弟是黑色的,兄弟的右孩子不是黑色的,而左孩子是黑色的。
3. 兄弟的节点都是黑色的,没法借,把兄弟节点涂成红色的,然后向上回溯,遇到红色直接涂成黑色,遇不到黑色,即祖先不是红的,让祖先向他的兄弟借,就继续执行这四种情况。没有就把祖先的兄弟的一个节点涂成红色。 如果祖先找到一个红的就涂黑,找不到就回溯,把兄弟涂红,大家都少一个黑色 最坏情况将所有的兄弟都涂成红色,每条路径少一个黑色。
4. 兄弟是红色,需要变色左旋,然后变成了上面三个情况
#include<iostream>
using namespace std;
template<typename T>
class RBTree{
public:
RBTree():root_(nullptr){};
void insert(const T&val){
if(root_== nullptr){
root_=new Node(val);
return ;
}
Node *parent = nullptr;
Node *cur =root_;
while(cur!= nullptr){
if(cur->data_>val){
parent=cur;
cur=cur->left_;
}else if(cur->data_<val){
parent=cur;
cur=cur->right_;
}else {
return;
}
}
// 设置当前节点的parent和颜色
Node *node =new Node(val,parent, nullptr, nullptr,RED);
if(parent->data_>val){
parent->left_=node;
}else {
parent->right_=node;
}
// 如果新插入的红色节点的父节点也是红色,不满足红黑树的性质,则进行插入调整操作
if(RED == color(parent)){
fixAfterInsert(node);
}
}
// 删除操作
void remove(const T&val){
if(root_== nullptr){
return;
}
Node* cur =root_;
while(cur!= nullptr){
if(cur->data_>val){
cur=cur->left_;
}else if(cur->data_<val){
cur=cur->right_;
}else{
break;
}
}
if(cur== nullptr){
return ;
}
// 删除cur节点
if(cur->left_!= nullptr && cur->right_!= nullptr){
Node *pre =cur->left_;
while(pre->right_!= nullptr){
pre=pre->right_;
}
cur->data_=pre->data_;
cur=pre; // cur指向前驱节点
}
// 前驱节点的左孩子或者有孩子
Node* child =cur->left_;
if(child== nullptr){
child=cur->right_;
}
if(child!= nullptr){
child->parent_=cur->parent_;
if(cur->parent_== nullptr){
root_=child;
}else {
if(cur->parent_->left_==cur){
cur->parent_->left_=child;
}else {
cur->parent_->right_=child;
}
}
Color c =color(cur);
delete cur;
if(c==BLACK){
fixAfterRemove(child);
}
}else{
if(cur->parent_== nullptr){
delete cur;
root_= nullptr;
return ;
}else{
//删除cur是叶子
if(color(cur)==BLACK){
fixAfterRemove(cur);
}
// 借到之后再删除
if(cur->parent_->left_==cur){
cur->parent_->left_= nullptr;
}else {
cur->parent_->right_= nullptr;
}
delete cur;
}
}
}
private:
// 节点颜色
enum Color{
BLACK,
RED
};
// 节点类型
struct Node{
Node(T data=T() , Node* parent= nullptr , Node *left = nullptr ,Node *right= nullptr,Color color=BLACK)
:data_(data),left_(left),right_(right),parent_(parent),color_(color){};
T data_;
Node *left_;
Node *right_;
Node *parent_; // 指向当前节点的父节点
Color color_; // 节点的颜色
};
// 获取节点颜色
Color color(Node *node){
return node== nullptr ? BLACK :node->color_;
}
// 设置节点颜色
void setColor(Node* node,Color color){
node->color_=color;
}
// 返回节点的左孩子
Node *left(Node *node){
return node->left_;
}
// 返回节点的右孩子
Node *right(Node *node){
return node->right_;
}
// 返回节点的父亲
Node* parent(Node *node){
return node->parent_;
}
// 左旋转
/*
1. 将孩子的父节点赋值为node的父节点,判断node的父节点是否空,也就是判断node是否为root,如果是就把root赋值为child,否则
改变node的父节点孩子的值,判断是在父节点的左子树还是右子树
2. 将child的left赋值给node的右子树,如果child的left不空的话,改变child的parent为node
3. 改变child的left为node,node的parent为child
*/
void leftRotate(Node *node){
Node * child = node->right_;
child->parent_=node->parent_;
if(node->parent_== nullptr){
root_=child;
}else{
if(node->parent_->left_==node){
node->parent_->left_=child;
}else{
node->parent_->right_=child;
}
}
node->right_=child->left_;
if(child->left_!= nullptr){
child->left_->parent_=node;
}
child->left_=node;
node->parent_=child;
}
// 右旋转
void rightRotate(Node *node){
Node *child=node->left_;
child->parent_==node->parent_;
if(node->parent_== nullptr){
root_=child;
}else{
if(node->parent_->left_==node){
node->parent_->left_=child;
}else{
node->parent_->right_=child;
}
}
node->left_=child->right_;
if(child->right_!= nullptr){
child->right_->parent_=node;
}
child->right_=node;
node->parent_=child;
}
// 红黑树插入调整操作
void fixAfterInsert(Node *node){
// 如果当前红色节点的父节点也是红色,继续调整
while(color(parent(node))==RED){
// 判断在爷爷的左子树还是右子树
if(left(parent(parent(node)))== parent(node)){
// 插入的节点在左子树中,uncle为空属于黑色
Node * uncle = right(parent(parent(node)));
// 情况一
if(RED == color(uncle)){
setColor(parent(node),BLACK);
setColor(parent(parent(node)),RED);
setColor(uncle,BLACK);
// 不知道爷爷和他的父亲是否有冲突,继续向上调整
node= parent(parent(node));
}else {
// 先处理情况三
if(right(parent(node))==node){
node = parent(node);
leftRotate(parent((node)));
}
// 处理情况二
setColor(parent(node),BLACK);
setColor(parent(parent(node)),RED);
rightRotate(parent(parent(node)));
// 不用继续处理了,局部性质未变,爷爷也是黑的,所以插入只要旋转两次
break;
}
}else{
// 插入的节点在右子树
Node * uncle = left(parent(parent(node)));
// 情况一
if(RED== color(uncle)){
setColor(parent(node),BLACK);
setColor(parent(parent(node)),RED);
setColor(uncle,BLACK);
// 不知道爷爷和他的父亲是否有冲突,继续向上调整
node= parent(parent(node));
}else {
// 先处理情况三
if(left(parent(node))==node){
node = parent(node);
rightRotate(parent((node)));
}
// 处理情况二
setColor(parent(node),BLACK);
setColor(parent(parent(node)),RED);
leftRotate(parent(parent(node)));
// 不用继续处理了,局部性质未变,爷爷也是黑的,所以插入只要旋转两次
break;
}
}
}
// 强制root为黑色
setColor(root_,BLACK);
}
// 红黑树删除调整操作
void fixAfterRemove(Node *node){
while(color(node)==BLACK){
if(left(parent(node))==node){
// 删除的黑色节点在左子树
Node* brother =right(parent(node));
if(color(brother)==RED){ // 情况四
setColor(parent(node),RED);
setColor(brother,BLACK);
leftRotate(parent(node));
brother= right(parent(node));
}
if(color(left(brother))==BLACK && color(right(brother))==BLACK){ // 情况三
setColor(brother,RED);
node = parent(node);
}else{
if(color(right(brother))!=RED){
setColor(brother,RED);
setColor(left((brother),BLACK));
rightRotate(brother);
brother= right(parent(node));
}
// 情况一
setColor(brother, color(parent(node)));
setColor(parent(node),BLACK);
setColor(right(brother),BLACK);
leftRotate(parent(node));
break;
}
}else{
// 删除的黑色节点在右子树
Node* brother =left(parent(node));
if(color(brother)==RED){ // 情况四
setColor(parent(node),RED);
setColor(brother,BLACK);
rightRotate(parent(node));
brother= left(parent(node));
}
if(color(left(brother))==BLACK && color(right(brother))==BLACK){ // 情况三
setColor(brother,RED);
node = parent(node);
}else{
if(color(left(brother))!=RED){
setColor(brother,RED);
setColor(right((brother),BLACK));
rightRotate(brother);
brother= left(parent(node));
}
// 情况一
setColor(brother, color(parent(node)));
setColor(parent(node),BLACK);
setColor(left(brother),BLACK);
rightRotate(parent(node));
break;
}
}
}
// 如果发现node指向的节点是红色,直接涂成黑色
setColor(node,BLACK);
}
Node *root_; // 指定根节点
};
int main(){
RBTree<int>rb;
for (int i = 0; i <=4 ; ++i) {
rb.insert(i);
}
return 0;
}