红黑树(算法导论)

测试代码所用的例子为算导第三版p179图13-4

#include <iostream>
using namespace std;

const bool BLACK = 0; // 黑色
const bool RED = 1; // 红色

struct node  // 结点结构 
{
	node *left;
	node *right;
	node *parent;
	int key;
	bool color;
	node(node *init, int data) : left(init), right(init), parent(init), key(data), color(BLACK) {}
};

class RB_tree
{
public:
	node *root; //  指向根结点
	node *nil; //   空节点(哨兵)(黑色)
	
	RB_tree(){ nil = new node(nullptr, -1); root = nil; } // 初始化nil结点和root
	node *left_rotate(node *x); // 左旋
	node *right_rotate(node *x); // 右旋
	void RB_insert(node *z); // 插入一个结点
	void RB_insert_fixup(node *z); // 插入后调整
	node *tree_minimum(node *x); // 找最小值
	node *tree_successor(node *x); // 找到x的后继
	node *RB_search(node *x, int k); // 查找元素
	node *RB_delete(node *z); // 删除一个结点
	void RB_delete_fixup(node *x); // 删除后调整
	void RB_print(node *x); 
	void print();// 输出
};

node *RB_tree::left_rotate(node *x) // 先将y的左孩子变为x的右孩子(y有做孩子的话) 
 {							       // 然后让y成为x父节点的右孩子(x为根节点的话 y直接变为根节点)					
	node *y = x->right;           //  最后让x变为y的左孩子
	x->right = y->left;
	if (y->left != nil)
	{
		y->left->parent = x;
	}
	y->parent = x->parent;
	if (x->parent == nil)
	{
		root = y;
	}
	else if (x->parent->left == x)
	{
		x->parent->left = y;
	}
	else 
	{
		x->parent->right = y;
	}
	y->left = x;
	x->parent = y;

	return y;
}

node *RB_tree::right_rotate(node *x)  // y的右孩子成为x的左孩子 y成为x父亲的孩子 x成为y的右孩子
{
	node *y = x->left;
	x->left = y->right;
	if (y->right != nil)
	{
		y->right->parent = x;
	}
	y->parent = x->parent;
	if (x->parent == nil)
	{
		root = y;
	}
	if (x->parent->right == x)
	{
		x->parent->right = y;
	}
	else
	{
		x->parent->left = y;
	}
	y->right = x;
	x->parent = y;

	return y;
}

void RB_tree::RB_insert(node *z)
{
	node *y = nil;
	node *x = root;
	// 利用x不断向下并赋值给y 找到z的插入点
	while (x != nil)
	{
		y = x;

		if (z->key < x->key)
		{
			x = x->left;
		}
		else
		{
			x = x->right;
		}
	}
	// 将 z插入到y的合适部位
	z->parent = y;

	if (y == nil) // 树空的时候 z成为根结点
	{
		root = z;
	}
	else if (z->key < y->key)
	{
		y->left = z;
	}
	else
	{
		y->right = z;
	}
	// 调整先插入的z的属性 然后调整 保持树的性质
	z->left = nil;
	z->right = nil;
	z->color = RED; // 必须为红 黑的话 会破坏树的性质
	RB_insert_fixup(z); // 向上调整维护树的性质
}

void RB_tree::RB_insert_fixup(node *z)
{
	node *y;
	while (z->parent->color == RED)
	{
		
		if (z->parent == z->parent->parent->left) 
		{
			y = z->parent->parent->right;
			if (y->color == RED)  // case 1 z的叔节点是红色的
			{
				z->parent->color = BLACK;
				y->color = BLACK;
				z->parent->parent->color = RED;
				z = z->parent->parent;
			}
			else  // case 2 z的叔节点黑色且z是右孩子
			{
				if (z == z->parent->right)
				{
					z = z->parent;
					left_rotate(z);
				}
				z->parent->color = BLACK;  // case 3 z的叔节点是黑色的且z是左孩子
				z->parent->parent->color = RED;
				right_rotate(z->parent->parent);
			}
		}
		else if (z->parent == z->parent->parent->right) // p[z]为右孩子的时候 与上面对称
		{
			y = z->parent->parent->left;
			if (y->color == RED)
			{
				z->parent->color = BLACK;
				y->color = BLACK;
				z->parent->parent->color = RED;
				z = z->parent->parent;
			}
			else 
			{
				if (z == z->parent->left)
				{
					z = z->parent;
					right_rotate(z);
				}
				z->parent->color = BLACK;
				z->parent->parent->color = RED;
				left_rotate(z->parent->parent);
			}
		}
	}
	root->color = BLACK;  // 根结点调整为黑色
}

node *RB_tree::tree_minimum(node *x) // 求最小值
{
	while (x->left != nil)
	{
		x = x->left;
	}
	return x;
}

node *RB_tree::tree_successor(node *x) // 寻找元素的后继
{
	if (x->right != nil) // 右子树不为空的话 在右子树中找到最小值就是
	{
		return tree_minimum(x->right);
	}
	node *y = x->parent; // 一直向上寻找
	while (y != nil && x == y->right)
	{
		x = y;
		y = y->parent;
	}
	return y;
}

node *RB_tree::RB_search(node *x, int k) // 寻找某个元素
{
	if (x->key == -1 || k == x->key)
	{
		return x;
	}
	if (k < x->key)
	{
		return RB_search(x->left, k);
	}
	else
	{
		return RB_search(x->right, k);
	}
}

node *RB_tree::RB_delete(node *z) // 删除某个元素 与BST基本一样
{
	node *x, *y;
	if (z->left == nil || z->right == nil)
		y = z;
	else
		y = tree_successor(z);
	
	if (y->left != nil)
		x = y->left;
	else
		x = y->right;

	x->parent = y->parent; // 不需要判断x是否为nil 无条件执行 BST要执行判断
	
	if (y->parent == nil)
	{
		root = x;
	}
	else if (y == y->parent->left)
	{
		y->parent->left = x;
	}
	else
	{
		y->parent->right = x;
	}

	if (y != z)
	{
		z->key = y->key;
	}
	
	if (y->color == BLACK) // 如果删除的是黑色结点 则向上调整树的性质 删除的是红色的什么也不影响 直接删掉即可
	{
		RB_delete_fixup(x);
	}
	return y;
}

void RB_tree::RB_delete_fixup(node *x) // 假设删除的y的黑色给了x x有了两层黑色这样可以满足性质5 只需要调整性质1 2 4即可
{
	node *w; // x的叔节点
	while (x != root && x->color == BLACK) //while循环的目的是将额外的黑色沿树上移(循环内部x时钟指向双重黑色结点) 														
	{													// 直到 1.x指向红黑结点,最后将x着色为(单个)黑
		if (x == x->parent->left)						//  2.x指向根节点 此时可以简单的移除额外的黑色	
		{												//  3.执行适当的旋转和重新着色 退出循环
			w = x->parent->right;

			if (w->color == RED) // case 1
			{
				w->color = BLACK;
				x->parent->color = RED;
				left_rotate(x->parent);
				w = x->parent->right;
			}

			if (w->left->color == BLACK && w->right->color == BLACK) // case 2
			{
				w->color = RED;
				x = x->parent;
			}
			else
			{
				if (w->right->color == BLACK) // case 3
				{
					w->left->color = BLACK;
					w->color = RED;
					right_rotate(w);
					w = x->parent->right;
				}
				w->color = x->parent->color; // case 4
				x->parent->color = BLACK;
				w->right->color = BLACK;
				left_rotate(x->parent);
				x = root;
			}
		}
		else if (x == x->parent->right) // x是右孩子的是 与上面对称的过程
		{
			w = x->parent->left;
			if (w->color == RED)
			{
				w->color = BLACK;
				x->parent->color = RED;
				right_rotate(x->parent);
				w = x->parent->left;
			}
			if (w->right->color == BLACK && w->left->color == BLACK)
			{
				w->color = RED;
				x = x->parent;
			}
			else
			{
				if (w->left->color == BLACK)
				{
					w->right->color = BLACK;
					w->color = RED;
					left_rotate(w);
					w = x->parent->left;
				}
				w->color = x->parent->color;
				x->parent->color = BLACK;
				w->left->color = BLACK;
				right_rotate(x->parent);
				x = root;
			}
		}
	}  
	x->color = BLACK;  // 目的是把新结点染为单一黑色
}

void RB_tree::RB_print(node *x) 
{
	if (x->key == -1)
	{
		return;
	}
	RB_print(x->left);
	cout << x->key << " " << x->color << endl;
	RB_print(x->right);
}

void RB_tree::print() // 中序遍历树 全部输出
{
	RB_print(root);
	cout << endl;
}

int main()
{
	RB_tree T;
	int s[9] = {7,2,11,1,5,8,14,4,15};
	for (int i = 0; i < 9; ++i)
	{
		node *z = new node(T.nil, s[i]);
		T.RB_insert(z);
		T.print();
	}
	cout << (*(T.root)).key << endl;
	T.RB_delete(T.root);

	cout << endl;
	T.print();

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值