赞
踩
红黑树的基本概念:
红黑树是一个平衡二叉树(左子节点比当前节点小,右子节点比当前节点大)。
一棵红黑树需要满足以下条件:
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;
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。