C++实现红黑树

红黑树实现

插入规则

当添加一个节点时旋转和颜色变换规则:
当前结点的父亲是红色,且它的祖父结点的另一个子结点也就是uncle节点也是红色就需要变色。
1.把父节点设为黑色
2.把叔叔也设为黑色
3.把祖父也就是父亲的父亲设为红色(爷爷)
4.把指针指向到祖父结点设为当前要操作的.
左旋:当前父结点是红色,叔叔是黑色的时候,且当前的结点是右子树。左旋以父结点作为左旋。
右旋:当前父结点是红色,叔叔是黑色的时候,且当前的结点是左子树。右旋
1.把父结点变为黑色
2.把祖父结点变为红色(爷爷)
3.以祖父结点旋转(爷爷)

删除规则

当删除一个节点时的变换规则:
自己是父亲的左儿子
自己为黑色、兄弟为红色、父节点为黑色
(1)将兄弟变成黑色,父节点变成红色;这时,以父节点为起点的左子树黑色高度降低
(2)对父节点进行左旋,以恢复左子树黑色高度;同时,兄弟的左孩子成为新的兄弟
此时,自己和兄弟都是黑色,父节点为黑色或红色;兄弟的两个儿子,都是黑色
(1)将兄弟变成为红色,x指向父节点,继续进行调整
此时,自己和兄弟均为黑色,父节点为红色或黑色;右侄子为黑色、左侄子为红色;
(1)将左侄子变成黑色,兄弟变为红色;这时,以兄弟为起点的右子树黑色高度降低
(2)将兄弟节点右旋,以恢复右子树的黑色高度;这时,左侄子将成为新的右兄弟
此时,自己和兄弟都是黑色,父节点为红色或黑色;右侄子为红色,左侄子为黑色或红色
(1)兄弟颜色改成与父节点一致,右侄子和父节点都变成黑色
(2)为了保证父节点变为黑色后,不影响所有路径的黑色高度,需要将父节点左旋(兄弟节点上提)
(3)x指向根节点,结束循环
自己是父亲的右儿子
此时,兄弟是红色节点,父节点必为黑色;若兄弟有左右儿子,左右儿子必为黑色
(1)将兄弟变成黑色节点,父节点变成红色;这时,以父节点为起点的右子树黑色高度降低
(2)将父节点右旋,以恢复右子树的黑色高度;这时,兄弟的右孩子成为新的兄弟
此时,自己和兄弟是黑色,父节点可以为红色或黑色
(1)将兄弟变成红色,x指向父节点,继续对父节点进行调整
此时,自己和兄弟均为黑色,父节点为黑色或红色;左侄子为黑色,右侄子为红色
(1)将右侄子变成黑色,兄弟变成红色;这是,以兄弟为起点的左子树黑色高度降低
(2)将兄弟左旋,以恢复左子树的黑色高度;这时,右侄子成为新的兄弟
此时,自己和兄弟均为黑色,父节点为红色或黑色;左侄子为红色,右侄子为红色或黑色
(1)将兄弟变成与父节点一样的颜色,左侄子和父节点变成黑色
(2)为了保证父节点变成黑色,不会影响所有路径的黑色高度,需要将父节点右旋(兄弟上提)
(3)x指向根节点,退出循环

RBTree.h:

#pragma once
#include<iostream>
#include<string>
#include<vector>
using namespace std;

#define RED  false
#define BLACK  true

struct RBNode {
	int value;
	RBNode* left;
	RBNode* right;
	RBNode* parent;
	bool color; //默认是红色(false)

	RBNode(int value) {
		this->value = value;
		this->left = nullptr;
		this->right = nullptr;
		this->parent = nullptr;
		this->color = RED;
	}
};
class RBTree
{
	RBNode *root = nullptr;
public:
	void insert(int val);//插入节点
	void setColor(RBNode * node, bool color);//修改节点颜色
	bool getColor(RBNode * node);//获取节点颜色空的为黑色
	void rightXuan(RBNode * pivot);//右旋
	void leftXuan(RBNode * pivot);//左旋
	void insertAdjust(RBNode*x);//调整插入后的颜色变换和旋转
	void printNode(RBNode*cur);//输出节点
	void deleteNode(int value);//删除节点
	void adjustDelete(RBNode*x);//删除前调整颜色变换和旋转
	RBNode*getRoot();//获取根节点
	RBNode*findNode(int value);//返回值为value的节点
	RBNode * returnLeft(RBNode * parent);//返回parent节点的左孩子节点
	RBNode * returnRight(RBNode * parent);//返回parent节点的右孩子节点
	RBNode * returnParent(RBNode * child);//返回child节点的父亲节点
};

RBTree.cpp

#include "RBTree.h"

//插入节点
void RBTree::insert(int value)
{
	RBNode* newNode = new RBNode(value);
	if (root == nullptr) {
		//根据红黑树的定义,根节点必须为黑色
		newNode->color = BLACK;
		root = newNode;
		return;
	}

	//根据数值大小寻找位置
	RBNode* cur = root;
	RBNode* p = cur;
	while (cur != nullptr) {
		p = cur;
		if (cur->value > value) {
			//小于去左子树
			cur = cur->left;
		}
		else if (cur->value == value) {
			cout << value << "不能插入相同元素" << endl;
			return;
		}
		else {
			//大于去右子树
			cur = cur->right;
		}
	}
	//插入节点
	if (p->value > value) {
		p->left = newNode;
	}
	else {
		p->right = newNode;
	}
	newNode->parent = p;

	//插入后调整平衡
	insertAdjust(newNode);
}

//插入调整
void RBTree::insertAdjust(RBNode*x)
{
	/*当前结点的父亲是红色,且它的祖父结点的另一个子结点也就是uncle节点也是红色就需要变色。
	1.把父节点设为黑色
	2.把叔叔也设为黑色
	3.把祖父也就是父亲的父亲设为红色(爷爷)
	4.把指针指向到祖父结点设为当前要操作的.
	左旋:当前父结点是红色,叔叔是黑色的时候,且当前的结点是右子树。左旋以父结点作为左旋。
	右旋:当前父结点是红色,叔叔是黑色的时候,且当前的结点是左子树。右旋
	5.把父结点变为黑色
	6.把祖父结点变为红色(爷爷)
	7.以祖父结点旋转(爷爷)*/
	while (returnParent(x) != nullptr && getColor(returnParent(x)) == RED) {
		if (returnLeft(returnParent(x)) == x) {//判断当前节点是左子树
			RBNode* uncle = returnRight(returnParent(returnParent(x)));
			if (getColor(uncle) == RED) {//判断叔叔
				setColor(returnParent(x), BLACK);//1.
				setColor(returnParent(returnParent(x)), RED);//3.
				setColor(uncle, BLACK);//2.
				x = returnParent(returnParent(x));//4.
			}
			else {//满足右旋条件
				rightXuan(returnParent(returnParent(x)));//7.
				setColor(returnParent(x), BLACK);//6.
				setColor(returnRight(returnParent(x)), RED);//5.
				//退出循环
				x = root;
			}

		}
		else {
			//满足左旋条件
			RBNode* uncle = returnLeft(returnParent(returnParent(x)));
			if (getColor(uncle) == RED) {//判断是变色还是旋转
				setColor(returnParent(x), BLACK);
				setColor(returnParent(returnParent(x)), RED);
				setColor(uncle, BLACK);
				x = returnParent(returnParent(x));
			}
			else {//左旋
				leftXuan(returnParent(returnParent(x)));
				setColor(returnParent(x), BLACK);
				setColor(returnLeft(returnParent(x)), RED);
				x = root;
			}
		}
	}
	//根节点必须是黑色的
	setColor(root, BLACK);
}

//先序遍历
void RBTree::printNode(RBNode * cur)
{
	if (cur == nullptr) {
		return;
	}
	cout << cur->value << " " << (cur->color == RED ? "red" : "black") << endl;
	printNode(cur->left);
	printNode(cur->right);

}

//删除
void RBTree::deleteNode(int value)
{
	RBNode* node = findNode(value);
	if (node == nullptr) {
		cout << "红黑树中不存在" << value << ",删除失败。" << endl;
		return;
	}
	//node为要删除的节点
	if (node->left != nullptr && node->right != nullptr) {
		//node节点的右子树的左节点
		RBNode* s = node->right;
		while (s != nullptr && s->left != nullptr) {
			s = s->left;
		}
		node->value = s->value;
		node = s;
	}
	//node为要删除的节点,replacement为代替node节点的节点
	RBNode* replacement = node->left == nullptr ? node->right : node->left;
	//删除的node节点是叶子节点
	if (replacement == nullptr) {
		//删除的是根节点,直接删除
		if (node->parent == nullptr) {
			root = nullptr;
		}
		else {
			//删除的node节点是黑色的,先调整
			if (getColor(node) == BLACK) {
				adjustDelete(node);
			}
			//再删除
			if (returnLeft(returnParent(node)) == node) {
				node->parent->left = nullptr;
			}
			else {
				node->parent->right = nullptr;
			}
			node->parent = nullptr;
		}
	}
	else {
		//node存在替代节点replacement,node节点一定是黑色节点,replacement节点一定是红色节点
		replacement->color = BLACK;
		replacement->parent = node->parent;
		//删除的是根节点
		if (node->parent == nullptr) {
			root = replacement;
		}
		else if (node->parent->left == node) {
			//删除的是父节点的左孩子
			node->parent->left = replacement;
		}
		else {
			//删除的是父节点的有孩子
			node->parent->right = replacement;
		}
		//删除node节点对其他节点的引用关系,使其变成垃圾被回收掉
		node->parent = node->left = node->right = nullptr;
	}
}

//删除调整
void RBTree::adjustDelete(RBNode * x)
{
	//x一定不是根节点且x节点一定是黑色的叶子节点
	while (returnParent(x) != nullptr && getColor(x) == BLACK) {
		//删除的x节点是父节点的左孩子
		if (returnLeft(returnParent(x)) == x) {//自己是左儿子
			RBNode* brother = returnRight(returnParent(x));
			if (getColor(brother) == RED) {//1.
				leftXuan(returnParent(x));
				setColor(brother, BLACK);
				setColor(returnParent(x), RED);
				brother = returnRight(returnParent(x));
			}
			if (getColor(returnLeft(brother)) == BLACK && getColor(returnRight(brother)) == BLACK) {
				setColor(brother, RED);
				x = returnParent(x);
			}
			else {
				if (getColor(returnRight(brother)) == BLACK) {
					rightXuan(brother);
					setColor(returnParent(brother), BLACK);
					setColor(brother, RED);
					brother = returnParent(brother);
				}
				leftXuan(returnParent(x));
				setColor(brother, getColor(returnParent(x)));
				setColor(returnParent(x), BLACK);
				setColor(returnRight(brother), BLACK);
				x = root;
			}
		}
		else {
			RBNode* brother = returnLeft(returnParent(x));
			if (getColor(brother) == RED) {
				rightXuan(returnParent(x));
				setColor(brother, BLACK);
				setColor(returnParent(x), RED);
				brother = returnLeft(returnParent(x));
			}

			if (getColor(returnLeft(brother)) == BLACK && getColor(returnRight(brother)) == BLACK) {
				setColor(brother, RED);
				x = returnParent(x);
			}
			else {
				if (getColor(returnLeft(brother)) == BLACK) {
					leftXuan(brother);
					setColor(brother, RED);
					setColor(returnParent(brother), BLACK);
					brother = returnParent(brother);
				}
				rightXuan(returnParent(x));
				setColor(brother, getColor(returnParent(x)));
				setColor(returnParent(x), BLACK);
				setColor(returnLeft(brother), BLACK);
				x = root;
			}
		}
	}
	setColor(x, BLACK);
}

 //返回根节点
RBNode * RBTree::getRoot()
{
	return root;
}

//寻找value值的节点
RBNode * RBTree::findNode(int value)
{
	RBNode* cur = root;
	while (cur != nullptr) {
		if (cur->value > value) {
			cur = cur->left;
		}
		else if (cur->value == value) {
			return cur;
		}
		else {
			cur = cur->right;
		}
	}
	return nullptr;
}

//返回parent节点的左孩子节点
RBNode*RBTree::returnLeft(RBNode*parent) {
	return parent == nullptr ? nullptr : parent->left;
}

//返回parent节点的右孩子节点
RBNode*RBTree::returnRight(RBNode*parent) {
	return parent == nullptr ? nullptr : parent->right;
}

//返回child节点的父亲节点
RBNode* RBTree::returnParent(RBNode*child) {
	return child == nullptr ? nullptr : child->parent;
}

//设置颜色
void RBTree::RBTree::setColor(RBNode*node, bool color) {
	if (node == nullptr) return;
	node->color = color;
}

//获取node节点的颜色
//如果node==nullptr,就返回黑色,否则返回node->color
bool RBTree::getColor(RBNode*node) {
	return node == nullptr ? BLACK : node->color;
}

//右旋
void RBTree::rightXuan(RBNode*Node) {
	RBNode* left = Node->left;
	Node->left = left->right;
	if (left->right != nullptr) {
		left->right->parent = Node;
	}
	if (Node->parent == nullptr) {
		//根节点为支点
		root = left;
	}
	else if (Node->parent->left == Node) {
		Node->parent->left = left;
	}
	else {
		Node->parent->right = left;
	}
	left->parent = Node->parent;
	left->right = Node;
	Node->parent = left;
}

//左旋
void RBTree::leftXuan(RBNode * Node)
{
	RBNode* right = Node->right;
	Node->right = right->left;
	if (right->left != nullptr) {
		right->left->parent = Node;
	}
	if (Node->parent == nullptr) {
		//根节点为支点
		root = right;
	}
	else if (Node->parent->left == Node) {
		Node->parent->left = right;
	}
	else {
		Node->parent->right = right;
	}
	right->parent = Node->parent;
	right->left = Node;
	Node->parent = right;
}

main.cpp:

#include"RBTree.h"

int main()
{
	vector<int>arr= { 13,8,17,12,11,15,25,6,22,27 };
	RBTree Tree ;
	for (int i = 0; i < arr.size(); i++) {
		Tree.insert(arr[i]);
	}
	Tree.deleteNode(11);
	Tree.deleteNode(12);
	Tree.printNode(Tree.getRoot());
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值