红黑树的基本概念:
红黑树是一个平衡二叉树(左子节点比当前节点小,右子节点比当前节点大)。
一棵红黑树需要满足以下条件:
1.根节点的颜色是黑色的。
2.一个节点要么是黑色,要么是红色。
3.红色节点的子节点必须是黑色节点。(红色节点被黑色节点隔开)
4.叶子节点的颜色是黑色的。
5.从根节点出发到叶子节点,每一条路径的黑色节点数量是相同的。(黑高)。
红黑树的类声明:
#include"iostream"
#include"math.h"
using namespace std;
#define RED 0
#define BLACK 1
class RBtree{
private:
// 红黑树的属性
public:
RBtree();
// 根节点
RBtree *root;
// 数据
int data;
// 颜色
bool color;
// 父亲节点
RBtree *parent;
// 左子节点
RBtree *left;
// 右子节点
RBtree *right;
// 节点插入函数,传入一个数据和一个根节点
RBtree *rbinsert(int data,RBtree *root);
// 节点删除传入一个要删除的数据和一个节点
RBtree *rbdelete(int data,RBtree *root);
// 节点的查找
RBtree *rbsearch(int data,RBtree *root);
// 最大值
RBtree *rbmax(RBtree *root);
// 最小值
RBtree *rbmin(RBtree *root);
// 右旋转
RBtree *rrotate(RBtree *root,RBtree *x);
// 左旋转
RBtree *lrotate(RBtree *root,RBtree *x);
// 插入修复
RBtree *rbinsertfixup(RBtree *x);
// 树的遍历
void rbprint(RBtree *x);
~RBtree();
};
红黑树的插入:
#include"RBtree.h"
// 插入修复
RBtree *insert_fixup(RBtree *root,RBtree *x)
{
// 如果x的父节点的color是red,并且x节点不是root节点
while (x->parent && x->parent->color==RED)
{
// 如果x的父是在祖父节点的左边
if(x->parent == x->parent->parent->left)
{
// 确定叔叔节点
RBtree *y = x->parent->parent->right;
// 情况1:y节点的颜色是red,并且y不是空节点
if(y && y->color==RED)
{
x->parent->color=BLACK;
y->color=BLACK;
x= y->parent;
x->color=RED;
}
// 情况2:y节点是黑色的,并且x的位置是三角型
else
if(x==x->parent->right)
{
x=x->parent;
root=root->lrotate(root,x);
}
// 情况3:y的节点是黑色,并且x的位置是直线
else
{
x->parent->color=BLACK;
x->parent->parent->color=RED;
root=root->rrotate(root,x->parent->parent);
}
}
else
// x的父节点在祖父节点的右边
{
// 确定叔叔节点
RBtree *y = x->parent->parent->left;
// 情况1:y节点的颜色是red,并且y不是空节点
if(y && y->color==RED)
{
x->parent->color=BLACK;
y->color=BLACK;
x= y->parent;
x->color=RED;
}
// 情况2:y节点是黑色的,并且x的位置是三角型
else
if(x==x->parent->left)
{
x=x->parent;
root=root->rrotate(root,x);
}
// 情况3:y的节点是黑色,并且x的位置是直线
else
{
x->parent->color=BLACK;
x->parent->parent->color=RED;
root=root->lrotate(root,x->parent->parent);
}
}
}
// 根节点的颜色始终是黑色
root->color=BLACK;
return root;
}
RBtree * RBtree::rbinsert(int data,RBtree *root)
{
// 实现将data插入rbtree
// 创建一个节点得到数据
RBtree *newnode = new RBtree;
newnode->data = data;
// 如果root为空,第一个节点
if(root== nullptr)
{
// 直接就是根节点
root=newnode;
}
// 如果root不为空
// 开始插入
else
{
//辅助指针
RBtree *x = root;
RBtree *y;
// 如果x不为空
while(x)
{
// y的位置始终在x的后面
y=x;
// 如果newnode的data比x的data小
if(newnode->data<x->data)
{
// 从左边走
x=x->left;
}
else
{
// 从右边走
x=x->right;
}
}
// 开始连接
// 确定newnode的父节点
newnode->parent=y;
if(newnode->data<y->data)
{
// 连接左边
y->left=newnode;
}
else
{
y->right=newnode;
}
}
// 对newnode节点进行修复
root=insert_fixup(root,newnode);
return root;
}
红黑树的删除:
#include"RBtree.h"
RBtree *delete_fixup(RBtree *root,RBtree *x)
{
while(x!=root && x->color==BLACK)
{
// 判断x的位置
if(x==x->parent->left)
{
// 确定w节点
RBtree *w=x->parent->right;
// 情况1:w是红色节点
if(w->color==RED)
{
// 将w的颜色染成黑色
w->color=BLACK;
// x的父节点的颜色染成红色
x->parent->color=RED;
// 对x的父节点左旋
root=root->lrotate(root,x->parent);
// 使得w成为新的兄弟节点
w=x->parent->right;
}
// 情况2:w的左右子节点都是黑色,或者w左右都是空节点,因为空节点的颜色本来就是黑色的
if((w->left==nullptr && w->right==nullptr)
// 或者w的left是一个黑节点或者w的right节点是一个空节点
|| (w->left && w->left->color==BLACK && w->right==nullptr)
// 或者w的right是一个黑色节点或者w的left节点是一个空节点
|| ((w->right && w->right->color==BLACK && w->left==nullptr))
|| (
// 确保w的左边和右边不是空节点
(w->left && w->right)
&&
// 确保w的左边和右边都是黑色节点
(w->left->color==BLACK && w->right->color==BLACK)
)
)
{
// w的颜色直接染成红色
w->color=RED;
// x直接上移一个
x=x->parent;
}
// 情况3:w右孩子是黑色,或者w的右孩子是空的
else
if(w->right==nullptr || w->right->color==BLACK)
{
w->left->color=BLACK;
w->color=RED;
root=root->rrotate(root,w);
w=x->parent->right;
}
// 情况4:结束
else
{
w->color=x->parent->color;
x->parent->color=BLACK;
// 判断w的right是否是节点
if(w->right)
{
w->right->color=BLACK;
}
root=root->lrotate(root,x->parent);
x=root;
}
}
else
{
// 确定w节点
RBtree *w=x->parent->left;
// 情况1:w是红色节点
if(w->color==RED)
{
// 将w的颜色染成黑色
w->color=BLACK;
// x的父节点的颜色染成红色
x->parent->color=RED;
// 对x的父节点右旋
root=root->rrotate(root,x->parent);
w=x->parent->left;
}
// 情况2:w的左右子节点都是黑色,或者w左右都是空节点,因为空节点的颜色本来就是黑色的
if((w->left==nullptr && w->right==nullptr)
// 或者w的left是一个黑节点或者w的right节点是一个空节点
|| (w->left && w->left->color==BLACK && w->right==nullptr)
// 或者w的right是一个黑色节点或者w的left节点是一个黑色节点
|| ((w->right && w->right->color==BLACK && w->left==nullptr))
|| (
// 确保w的左边和右边不是空节点
(w->left && w->right)
&&
// 确保w的左边和右边都是黑色节点
(w->left->color==BLACK && w->right->color==BLACK)
)
)
{
// w的颜色直接染成红色
w->color=RED;
// x直接上移一个
x=x->parent;
}
// 情况3:w右孩子是黑色,或者w的右孩子是空的
else
if(w->left==nullptr || w->left->color==BLACK)
{
w->right->color=BLACK;
w->color=RED;
root=root->lrotate(root,w);
w=x->parent->left;
}
// 情况4:结束
else
{
w->color=x->parent->color;
x->parent->color=BLACK;
// 判断w的left是否是节点
if(w->left)
{
w->left->color=BLACK;
}
root=root->rrotate(root,x->parent);
x=root;
}
}
}
x->color=BLACK;
return root;
}
RBtree *RBtree::rbdelete(int data,RBtree *root)
{
// 搜索节点要删除的节点
RBtree *delenode = root->rbsearch(data,root);
// 直到delenode被释放
while(delenode!=nullptr)
{
// 如果删除的是根节点
if(delenode == root)
{
// 如果根节点有两个子节点
if(delenode->right && delenode->left)
{
// 首先找到delenode的right的最小值
RBtree *rmin = delenode->rbmin(delenode->right);
// 把rmin的data给到delenode的data
delenode->data=rmin->data;
// 直接去删除rmin
delenode = rmin;
// // 就直接把delenode的data改成,deletnode的right的最小值
// delenode->data=delenode->right->rbmin(delenode->right)->data;
// // 去删除delenode
// delenode=delenode->right->rbmin(delenode->right);
}
else
// 如果根节点只有一个右节点
if(delenode->right)
{
// 对delenode 修复
root=delete_fixup(root,delenode);
// 新的根
root=delenode->right;
root->parent = nullptr;
//删除根
delete delenode;
delenode =nullptr;
}
else
// 根节点只有一个左节点
if(delenode->left)
{
// 对delenode 修复
root=delete_fixup(root,delenode);
root=delenode->left;
root->parent=nullptr;
delete delenode;
delenode = nullptr;
}
else
// 删除根节点
{
root =nullptr;
delete delenode;
delenode = nullptr;
}
}
// 删除的是除了根节点以外的节点
else
{
// 判断要删除节点的方向
if(delenode->parent->left==delenode)
{
// 要删除的节点在delenod的父节点的左边
//
if(delenode->right && delenode->left)
{
// 情况1:delenode有两个子节点
RBtree *rmin = root->rbmin(delenode->right);
// 替换内容
delenode->data=rmin->data;
// 直接删除rmin
delenode = rmin;
// 将第四种情况转换成第一种情况
}
else
if(delenode->left)
{
// 对delenode 修复
root=delete_fixup(root,delenode);
// 情况2:deletnode有一个left节点
// delenode父节点的左边连接denode的左边
delenode->parent->left=delenode->left;
// delenode的的左孩子的父节点连接delenode的父节点
delenode->left->parent=delenode->parent;
// 删除节点
delete delenode;
delenode = nullptr;
}
else
if(delenode->right)
{
// 对delenode 修复
root=delete_fixup(root,delenode);
// 情况3:deletnode有一个right节点
// delenode父节点的左边连接denode的左边
delenode->parent->left=delenode->right;
// delenode的的左孩子的父节点连接delenode的父节点
delenode->right->parent=delenode->parent;
// 删除节点
delete delenode;
delenode = nullptr;
}
else
{
// 对delenode 修复
root=delete_fixup(root,delenode);
// 情况4:delenode没有子节点
delenode->parent->left =nullptr;
delete delenode;
delenode=nullptr;
}
}
else
{
// 要删除的节点在delenod的父节点的右边
//
if(delenode->right && delenode->left)
{
// 情况1:delenode有两个子节点
RBtree *rmin = root->rbmin(delenode->right);
// 替换内容
delenode->data=rmin->data;
// 直接删除rmin
delenode = rmin;
// 将第四种情况转换成第一种情况
}
else
if(delenode->left)
{
// 对delenode 修复
root=delete_fixup(root,delenode);
// 情况2:deletnode有一个left节点
// delenode父节点的左边连接denode的左边
delenode->parent->right=delenode->left;
// delenode的的左孩子的父节点连接delenode的父节点
delenode->left->parent=delenode->parent;
// 删除节点
delete delenode;
delenode = nullptr;
}
else
if(delenode->right)
{
// 对delenode 修复
root=delete_fixup(root,delenode);
// 情况3:deletnode有一个right节点
// delenode父节点的左边连接denode的左边
delenode->parent->right=delenode->right;
// delenode的的左孩子的父节点连接delenode的父节点
delenode->right->parent=delenode->parent;
// 删除节点
delete delenode;
delenode = nullptr;
}
else
{
// 对delenode 修复
root=delete_fixup(root,delenode);
// 情况4:delenode没有子节点
delenode->parent->right =nullptr;
delete delenode;
delenode=nullptr;
}
}
}
}
return root;
}
寻找节点的最大值
// 查找最大值
#include"RBtree.h"
RBtree *RBtree::rbmax(RBtree *root)
{
RBtree *x =root;
RBtree *y;
while (x)
{
y=x;
x=x->right;
}
return y;
}
寻找最小值:
// 查找最小值
#include"RBtree.h"
RBtree *RBtree::rbmin(RBtree *root)
{
RBtree *x =root;
RBtree *y;
while (x)
{
y=x;
x=x->left;
}
return y;
}
红黑树的遍历输出:
#include"RBtree.h"
// 树的遍历
void RBtree::rbprint(RBtree *x)
{
if(x)
{
rbprint(x->left);
cout<<x->data<<endl;
rbprint(x->right);
}
}
红黑树的查找:
#include"RBtree.h"
// rb树的查找
RBtree* RBtree::rbsearch(int data,RBtree *root)
{
RBtree *snode =root;
while (snode!=nullptr)
{
// 如果snode的data比data要小
if(snode->data<data)
{
// 右边走
snode=snode->right;
}
// 如果snode的data比data要大
else if(snode->data>data)
{
// 左边边走
snode = snode->left;
}
else
{
// 找到了
// 返回这个节点的地址
return snode;
}
}
return nullptr;
}
红黑树的左旋:
#include"RBtree.h"
// 左旋转
RBtree *RBtree::lrotate(RBtree *root,RBtree *x)
{
// 根节点的旋转
RBtree *y;
// y在x的右边
y=x->right;
// 开始旋转
if(x == root)
{
// 如果x的right不是空节点
if(x->right)
{
// x的右边
x->right=y->left;
// 判断y的left是否有节点
if(y->left)
{
y->left->parent=x;
}
// y的左边
y->left=x;
x->parent=y;
// 连接root
root=y;
y->parent=nullptr;
}
}
else
{
// 判断x是左孩子还是右孩子
if(x->parent->left==x)
{
// x在父节点的左边
// 改变x父节点到y
x->parent->left=y;
}
else
{
// x在父节点的右边
// 改变x父节点到y
x->parent->right=y;
}
y->parent=x->parent;
// x的右边
x->right=y->left;
// 判断y是否有left节点
if(y->left)
{
y->left->parent=x;
}
// y的左边
y->left=x;
x->parent=y;
}
return root;
}
红黑树的右旋:
#include"RBtree.h"
// 右旋转
RBtree *RBtree::rrotate(RBtree *root,RBtree *x)
{
// 根节点的旋转
RBtree *y;
// y在x的左边
y=x->left;
// 开始旋转
if(x == root)
{
// 如果x的left不是空节点
if(x->left)
{
// x的左边
x->left=y->right;
// 判断y的left是否有节点
if(y->right)
{
y->right->parent=x;
}
// y的右边
y->right=x;
x->parent=y;
// 连接root
root=y;
y->parent=nullptr;
}
}
else
{
// 判断x是左孩子还是右孩子
if(x->parent->right==x)
{
// x在父节点的右边
// 改变x父节点到y
x->parent->right=y;
}
else
{
// x在父节点的右边
// 改变x父节点到y
x->parent->left=y;
}
y->parent=x->parent;
// x的左边
x->left=y->right;
// 判断y是否有left节点
if(y->right)
{
y->right->parent=x;
}
// y的右边
y->right=x;
x->parent=y;
}
return root;
}