红黑树学习笔记

1、红黑树的应用

	Map、Nginx、定时器、内存管理

2、红黑树的五大特性

  1. 每个节点要么是红色,要么是黑色;
  2. 根节点永远是黑色的;
  3. 所有的叶节点都是是黑色的(注意这里说叶子节点其实是 NIL 节点,被隐藏的);
  4. 每个红色节点的两个子节点一定都是黑色;
  5. 从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点;

将下述数组中的Key依次插入就生成了下图的平衡二叉树
int keyArray[20] = {24,25,13,35,23,26,67,47,38,98, 20,19,17,49,12, 21,9,18,14,15};

在这里插入图片描述

3、红黑树的旋转

在这里插入图片描述
红黑树的旋转–需要调整三个方向,旋转时暂时先不考虑颜色

3.1 左旋–针对X节点

 1、X的右节点指向Y的左节点(b),Y的左节点(b)的父亲变为x
 2、Y的父亲指向X的父亲,X的父亲的左/右孩子变为Y
 3、Y的左子树变为X,X的父亲变为Y

对应代码如下

void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
	rbtree_node *y = x->right;  // x  --> y  ,  y --> x,   right --> left,  left --> right
	x->right = y->left; //1 1
	if (y->left != T->nil) { //1 2
		y->left->parent = x;
	}

	y->parent = x->parent; //1 3
	if (x->parent == T->nil) { //1 4
		T->root = y;
	} else if (x == x->parent->left) {
		x->parent->left = y;
	} else {
		x->parent->right = y;
	}

	y->left = x; //1 5
	x->parent = y; //1 6
}

3.2 右旋–针对Y节点

1、Y的左子树指向X的右子树,X的右子树的父亲变为Y
2、X的父亲变为Y的父亲
3、Y变为X的右子树
代码如下–就是将左旋的代码Y改为X,X改为Y,left改为right,right改为left

void rbtree_right_rotate(rbtree *T, rbtree_node *y) {

	rbtree_node *x = y->left;

	y->left = x->right;
	if (x->right != T->nil) {
		x->right->parent = y;
	}

	x->parent = y->parent;
	if (y->parent == T->nil) {
		T->root = x;
	} else if (y == y->parent->right) {
		y->parent->right = x;
	} else {
		y->parent->left = x;
	}

	x->right = y;
	y->parent = x;
}

4、红黑树插入

前提–插入时已经是一颗满足条件的红黑树
由于插入前黑高已经固定,所以我们插入的肯定是一个红色节点(不能打破性质5),所以可以推断出如下4种插入情况

(1)新节点位于根节点,其没有父节点,处理思路:将该节点直接设为黑色即可
(2)新节点的父节点已然是黑色,处理思路:不用动,这已然是一颗红黑树,直接插入 (key=98节点)
添加key==98这个节点
(3)父节点和叔节点都是红色
处理思路:a.将父节点和叔节点设为黑色;b.将祖父节点设为红色;c.将祖父节点设为当前节点,并继续对新当前节点进行操作,直到此树平衡(添加节点key=19)
添加节点19
对应代码如下

	//y是要插入节点z的叔叔节点
	rbtree_node *y = z->parent->parent->right;
	if (y->color == RED)//父节点红色,叔节点也是红色
	{
		z->parent->color = BLACK; //父节点设为黑色
		y->color = BLACK; //叔节点设为黑色
		z->parent->parent->color = RED;//祖父节点设为红色
	
		z = z->parent->parent; //祖父节点设为当前节点,继续操作
	}

(4)父节点是红色,叔节点是黑色,又分如下四种情况:
a.当前节点是父亲的左孩子,父亲是祖父的左孩子(Left-Left),
处理思路:1.将祖父节点右旋;2.交换父节点和祖父节点的颜色
注意:下图的17不是新插入的,此时正在调整过程中
在这里插入图片描述
在这里插入图片描述

b.当前节点是父亲的右孩子,父亲是祖父的左孩子(Right-Left),
处理思路:1.将父节点左旋,并将父节点作为当前节点; 2.然后再使用Left Left情形
在这里插入图片描述

c.当前节点是父亲的右孩子,父亲是祖父的右孩子(Right-Right)key=35是新插入的节点
处理思路:1.将祖父节点左旋;2.交换父节点和祖父节点的颜色
在这里插入图片描述

d.当前节点是父亲的左孩子,父亲是祖父的右孩子(Left-Right),key=26是新插入的节点
处理思路:1.将父节点右旋,并将父节点作为当前节点(此时35作为新插入的节点);
2.然后再使用Right Right情形
add26
add26

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值