红黑树图解(插入、删除)

本文介绍了红黑树与AVL树的区别,红黑树作为平衡二叉查找树的一种,允许节点间的不平衡,而AVL树要求严格平衡。在红黑树的插入操作中,通过特定的旋转和颜色调整保持平衡。插入操作后可能需要进行左旋、右旋以及颜色修正来维护红黑树的性质。文章详细阐述了这些过程,并提供了相应的代码实现。
摘要由CSDN通过智能技术生成

红黑树同AVL树(平衡二叉树),都是在进行插入和删除时,通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。俩者不同的是:AVL树是严格的平衡二叉树,平衡条件必须满足所有节点的左右子树高度差不超过1,而红黑树只是尽量达到平衡,可以存在左右子树高度差超过1的情况存在。


红黑树性质:

1、每一个节点要么黑色要么红色。

2、根节点一定为黑色。

3、每一个叶子节点(每条树枝末端隐藏的空节点NIL)都为黑色。

4、每一个红色的节点的俩个子节点必为黑色(即不能存在连续俩个红色节点相连)。

5、每一个节点的所有支路到叶子节点途径上有相同的黑色节点数目。

// 枚举节点颜色类型
enum COLOR { RED, BLACK };
typedef int keyType;
// 节点
class RBTNode {
public:
	RBTNode(keyType key) :Key(key), Left(NULL), Right(NULL), Parent(NULL), Color(RED) {} 
	keyType Key;
	RBTNode* Left;
	RBTNode* Right;
	RBTNode* Parent;
	COLOR Color;
};
// 红黑树
class RBT {
public:
	bool Insert(keyType key);		// 插入
	bool Delete(keyType key);		// 删除
	RBT() :Root(NULL) {}
	RBT(keyType key) :Root(new RBTNode(key)) {}
	RBTNode* Root;
};

 插入

// 插入
bool RBT::Insert(keyType key) {
	if (NULL == Root) {
		Root = new RBTNode(key);
		Root->Color = BLACK;
		return true;
	}
	RBTNode* T = Root;
	while (1) { 
		if (key == T->Key) return false;
		else if (key < T->Key) {
			if (NULL == T->Left) break;
			T = T->Left;
		}
		else {
			if (NULL == T->Right) break;
			T = T->Right;
		}
	}
	if (key < T->Key) {
		T->Left = new RBTNode(key);
		T->Left->Parent = T;
		T = T->Left;
	}
	else {
		T->Right = new RBTNode(key);
		T->Right->Parent = T;
		T = T->Right;
	}
	// 颜色修正
	RBT_Fix(*this, T);
	return true;
}

 节点插入插入操作跟二叉查找树相同,区别在与,插入之后节点的颜色是否需要改变。

旋转操作:

左旋:

右旋: 

// 左旋
void LRotate(RBT &Tree, RBTNode* node) { 
	RBTNode* T = node->Right;
	RBTNode* P = node->Parent;
	node->Right = T->Left;
	T->Left = node;
	if (node->Right) node->Right->Parent = node;
	T->Parent = P;
	node->Parent = T;
	if (NULL == T->Parent) Tree.Root = T;
	else {
		if (node == P->Left) P->Left = T;
		else P->Right = T;
	}
}
// 右旋
void RRotate(RBT &Tree, RBTNode* node) {
	RBTNode* T = node->Left;
	RBTNode* P = node->Parent;
	node->Left = T->Right;
	T->Right = node;
	if (node->Left) node->Left->Parent = node;
	T->Parent = P;
	node->Parent = T;
	if (NULL == T->Parent) Tree.Root = T;
	else {
		if (node == P->Left) P->Left = T;
		else P->Right = T;
	}
}

节点颜色调节: 

默认插入节点的颜色为红色。若为黑色则会频繁违反黑红树的性质5,需要频繁的调整。

1. 当插入节点的父节点为黑色时,不影响红黑树的结构性质,不需要进行调整。

2. 当父节点为红色时,又存在不同的情况。

        2.1 父节点的兄弟节点(叔节点)为红色,则祖父节必定存在且为黑色。

       

        将祖父节点变为红色,父节点和叔节点变为黑色,将祖父节点设为新的插入节点。这只是            局部的调整完毕,将祖父节点变为红色,若祖父节点的父节点为红色则会再次失衡,所以需            将祖父节点设为新的插入节点判断是否需要变色调整)

        2.2 叔节点的颜色为黑色,又分俩种情况

                2.2.1 插入节点为父节点的左孩子

                         2.2.1.1 父节点为祖父节点的左孩子。将祖父节点变为红,父节点变为黑,右旋祖                             父节点 

                         2.2.1.2 父节点为祖父节点的右孩子。右旋父节点,将父节点和插入节点互换,变                             为2.2.2.2的情况。

                2.2.2 插入节点为父节点的右孩子

                         2.2.2.1 父节点为祖父节点的左孩子。左旋父节点,将父节点和插入节点互换,变                             为2.2.1.1的情况。

                         2.2.2.2 父节点为祖父节点的右孩子。将父节点变为黑色,祖父节点变为红色,左                             旋祖父节点。

                          

        


// 改色
void RBT_Fix(RBT &Tree, RBTNode* node) {
	RBTNode* P = node->Parent;
	RBTNode* GP = NULL;
	RBTNode* U = NULL;
	// 1. 父亲节点为红(必存在祖父节点)
	while (P&&P->Color == RED) {
		GP = P->Parent;
		// 1.1 父为祖父左孩子
		if (P == GP->Left) {
			U = GP->Right;
			// 1.1.1 叔节为红 ---> 祖父节点必为黑  黑红红--> 红黑黑
			if (U&&U->Color == RED) {
				GP->Color = RED;
				P->Color = BLACK;
				U->Color = BLACK;
				node = GP;
				P = node->Parent;
			}
			// 1.1.2 叔节点为黑(含NIL黑节点)
			else {
				// 1.1.2.1 插入节点为P 的左孩子
				if (node == P->Left) {
					GP->Color = RED;
					P->Color = BLACK;
					RRotate(Tree, GP);
				}
				// 1.1.2.1	插入节点为P 的右孩子
				else {
					RBTNode* T = P;
					LRotate(Tree, P);
					P = node;
					node = T;
				}
			}
		}
		// 1.2 父为祖父右孩子
		else {
			U = GP->Left;
			// 1.2.1 叔节点为红色
			if (U&&U->Color == RED) {
				GP->Color = RED;
				P->Color = BLACK;
				U->Color = BLACK;
				node = GP;
				P = node->Parent;
			}
			// 1.2.2 叔节点为黑色
			else {
				// 插入节点为父节点的左孩子  
				if (node == P->Left) {
					RBTNode* T = P;
					RRotate(Tree, P);
					P = node;
					node = P;
				}
				// 插入节点为父节点的右孩子
				else {
					GP->Color = RED;
					P->Color = BLACK;
					LRotate(Tree, GP);
				}
			}
		}
	}
	// 2. 父亲节点为黑 (不需要调整)
	Tree.Root->Color = BLACK;
}

删除

红黑树的删除操作相较于插入操作更加复杂,另开一篇记录,红黑树删除

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值