#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#pragma warning(disable:4996)
using namespace std;
struct RBNode {
int value;
bool color; //是否为红色
RBNode *parent;
RBNode *left, *right;
RBNode* GetChild(bool isLeft) {
return true == isLeft ? left : right;
}
void SetChild(bool isLeft, RBNode* value) {
if (true == isLeft) {
this->left = value;
}
else {
this->right = value;
}
}
RBNode(RBNode* _parent, bool isLeft, int _value, bool _color) {
this->value = _value;
this->color = _color;
this->left = NULL;
this->right = NULL;
this->parent = _parent;
if (NULL != this->parent) {
this->parent->SetChild(isLeft, this);
}
}
bool IsLeft() {
return this->parent->left == this;
}
RBNode* GetBrother() {
return (this->IsLeft()) ? this->parent->right : this->parent->left;
}
RBNode* GetUncle() {
if (this->parent && this->parent->parent) {
return this->parent->parent->GetChild(!this->parent->IsLeft());
}
return NULL;
}
};
//查找结点
RBNode* RBFind(RBNode* rt, int value) {
if (NULL == rt) {
return NULL;
}
RBNode* nNode = rt;
while (NULL != nNode && value != nNode->value) {
nNode = nNode->GetChild(value < nNode->value);
}
return nNode;
}
//查找后继结点
RBNode* RBFindSuccessor(RBNode* rt, bool isLeft) {
RBNode* retNode = rt->GetChild(isLeft);
if (NULL == retNode) {
return rt;
}
RBNode* chdNode = retNode;
while (NULL != chdNode) {
retNode = chdNode;
chdNode = chdNode->GetChild(!isLeft);
}
return retNode;
}
//旋转
void Rotate(RBNode* rt, bool isLeftRotate) {
RBNode* pre = rt->parent;
RBNode* chd = rt->GetChild(!isLeftRotate);
if (NULL != chd->GetChild(isLeftRotate)) {
chd->GetChild(isLeftRotate)->parent = rt;
}
rt->SetChild(!isLeftRotate, chd->GetChild(isLeftRotate));
chd->parent = pre;
if (NULL != pre) {
pre->SetChild(rt->IsLeft(), chd);
}
rt->parent = chd;
chd->SetChild(isLeftRotate, rt);
}
//插入调整
void InsertFixup(RBNode* curNode) {
while (NULL != curNode->parent && true == curNode->parent->color) {
//父结点是红色,需要调整
//目的是把父结点染成黑色,
RBNode* uncleNode = curNode->GetUncle();
if (NULL != uncleNode && true == uncleNode->color) {
//叔叔是红色,祖父结点肯定是黑色,只需要把叔叔和父结点同时染黑,祖父结点染红
uncleNode->color = false;
curNode->parent->color = false;
curNode->parent->parent->color = true;
//祖父结点变红后可能影响结构
curNode = curNode->parent->parent;
}
else {
//叔叔结点是黑色
if (curNode->IsLeft() != curNode->parent->IsLeft()) {
//和父结点方向不同,通过旋转使之同向
bool rDir = !(curNode->IsLeft());
curNode = curNode->parent;
Rotate(curNode, rDir);
}
//和父结点同方向
curNode->parent->color = false;
curNode->parent->parent->color = true;
Rotate(curNode->parent->parent, !curNode->IsLeft());
}
}
if (NULL == curNode->parent) {
//根结点是黑色
curNode->color = false;
}
}
RBNode* RBInsert(RBNode* rt, int value) {
RBNode* newParent = NULL;
//查找结点位置
RBNode* tmpNode = rt;
while (NULL != tmpNode) {
newParent = tmpNode;
tmpNode = tmpNode->GetChild(value < tmpNode->value);
}
//创建新结点
RBNode* newNode = new RBNode(newParent, (NULL != newParent && value < newParent->value), value, true);
if (NULL == rt) {
rt = newNode;
}
//调整树结构
InsertFixup(newNode);
//返回根结点
while (NULL != rt && NULL != rt->parent) {
rt = rt->parent;
}
return rt;
}
//删除调整
void DeleteFixup(RBNode* curNode) {
while (NULL != curNode->parent && false == curNode->color) {
RBNode* brother = curNode->GetBrother();
if (NULL != brother && true == brother->color) {
//兄弟结点是红色
brother->color = false;
curNode->parent->color = true;
Rotate(curNode->parent, curNode->IsLeft());
}
else {
//兄弟结点是黑色
//同方向的侄子
RBNode* scorpion1 = brother->GetChild(curNode->IsLeft());
//另一个侄子
RBNode* scorpion2 = brother->GetChild(!curNode->IsLeft());
if ((NULL == scorpion1 || false == scorpion1->color) && (NULL == scorpion2 || false == scorpion2->color)) {
//两个侄子都是黑色
//这里无需考虑parent是红色,因为循环条件是当前结点为黑色,如果是红色会在循环结束后改为黑色
brother->color = true;
//父结点设置为当前结点,重新调整
curNode = curNode->parent;
}
else {
if (NULL == scorpion2 || false == scorpion2->color) {
//反方向的侄子是黑色,同方向是红色
//把红色旋转到反方向,然后再后面的代码中处理
brother->color = true;
scorpion1->color = false;
Rotate(brother, !scorpion1->IsLeft());
//兄弟,侄子结点变了
brother = curNode->GetBrother();
scorpion1 = brother->GetChild(curNode->IsLeft());
scorpion2 = brother->GetChild(!curNode->IsLeft());
}
//反方向侄子是红色
brother->color = curNode->parent->color;
curNode->parent->color = false;
scorpion2->color = false;
//这句是为了退出循环,退出循环后还是会改为黑色
curNode->color = true;
Rotate(curNode->parent, curNode->IsLeft());
}
}
}
curNode->color = false;
}
//删除
RBNode* RBDelete(RBNode* rt, int value) {
//查找
RBNode* curNode = RBFind(rt, value);
if (NULL == curNode) {
return rt;
}
//替换结点
RBNode* relNode = NULL;
if (NULL == curNode->left || NULL == curNode->right) {
relNode = curNode;
}
else {
relNode = RBFindSuccessor(curNode, false);
}
//替换结点的子结点
RBNode* relNodeChd = relNode->GetChild(NULL != relNode->left);
//删除curNode
curNode->value = relNode->value;
if (NULL == relNode->parent) {
//删除结点是根结点
rt = relNodeChd;
if (NULL != rt) {
rt->parent = NULL;
//把rt变成黑色
DeleteFixup(rt); //和rt->color = false一样
}
}
else if (NULL == relNodeChd) {
//替换结点没有子结点
if (false == relNode->color) {
//替换结点是黑色,重新调整树结构
DeleteFixup(relNode);
}
//删除relNode
relNode->parent->SetChild(relNode->IsLeft(), NULL);
relNode->parent = NULL;
}
else if (false == relNode->color) {
//架空替换结点
if (NULL != relNodeChd) {
relNodeChd->parent = relNode->parent;
}
relNode->parent->SetChild(relNode->IsLeft(), relNodeChd);
//如果替换结点是黑色,需要调整结构
DeleteFixup(relNodeChd);
}
delete relNode;
//返回根结点
while (NULL != rt && NULL != rt->parent) {
rt = rt->parent;
}
return rt;
}
void PrintTree(RBNode* rt, int stru, int layer) {
if (NULL == rt) return;
//先输出前缀
int pos = 1;
for (int i = 0; i < layer; i++) {
pos = (1 << i);
if (pos & stru) {
printf("%-8s", "|");
}
else {
printf("%-8s", " ");
}
}
//输出自己
printf("%-8s", "+-------");
printf("%d(%s)\n", rt->value, rt->color ? "R" : "B");
int new_stru = stru | ((NULL == rt->parent || rt->IsLeft() ? 0 : 1) << layer);
//先遍历右孩子
PrintTree(rt->right, new_stru, layer + 1);
//再遍历左孩子
PrintTree(rt->left, new_stru, layer + 1);
}
红黑树-RBTree
最新推荐文章于 2022-11-03 13:31:25 发布