红黑树-RBTree

#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);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

achonor

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值