算法【树】| 红黑树总结

【参考】:
维基百科
【喵的算法课】红黑树 删除【12期】

1 红黑树演变

演变:线性查找(性能低O(n))—>二分查找((logn) 二查叉树会出现退化成链表的问题)
	—>出现AVL平衡二叉树(数据变化有频繁更新节点问题)—>出现红黑树O(logn);

可见黑红树是在平衡二叉树的基础上,在数据的插入和删除上有所提升;

2 红黑树简介

红黑树是一棵近似平衡二叉搜索树,其中序遍历单调不减,并且能确保任何一个结点的左右子树的高度差小于两倍;
    恢复红黑树的性质需要少量的颜色变更和不超过三次树旋转(对于插入操作是两次);

3 红黑树的性质

【1】结点是红或黑色;
【2】根节点是黑色;
【3】所有的叶子结点都是黑色;
【4】每个红色结点的两个子结点都是黑色,且一条路径上红色结点不能连续;
【5】从任一结点其每个叶子的所有路径都包含相同数目的黑色结点;

【特性】从根到叶子的最长的可能路径不多于最短的可能路径的两倍长;

4 红黑树操作

4.1 在插入和删除的注意事项

- 性质1和性质3总是保持着;
- 性质4只在增加红色节点、重绘黑色节点为红色,或做旋转时受到威胁;
- 性质5只在增加黑色节点、重绘红色节点为黑色,或做旋转时受到威胁;

4.2 基础知识

4.2.1 父结点以及叔结点

在这里插入图片描述

 node* grandparent (node *n){
     return n->parent->parent;
 }

 node* uncle(node *n){
     if(n->parent == grandparent(n)->left)
         return grandparent(n)->right;
     else
         return grandparent(n)->left;
 }
4.2.2 左右旋转

在这里插入图片描述

4.2.2 几种删除情况

情况1
在这里插入图片描述
情况2
在这里插入图片描述情况3

若删除B,则找到相应的前驱结点(左子树中最大的结点)或后继结点(右子树中最小的结点)来代替;

在这里插入图片描述

4.3 插入

- 一般插入将该结点设置为红色,由于最差的情况是导致两个红色冲突,而只需要对其进行旋转或颜色调整即可;若使用
黑色,则该路径上会多出一个黑色结点,比较难调整;

【插入操作】: p为被插入结点
	【1】若p是根结点:直接将该结点设为黑色(注:此时该树为空树,插入的结点即为根结点);
	【2】若p的父节点为黑色:不需要处理;
	【3】若p的父节点是红色:
		- 【3】若p的叔节点为红色;
			- 将父节点设为黑色;
			- 将叔叔结点设为黑色;
			- 将祖父结点设为红色;
			- 此时将祖父结点设为当前结点去递归从情形1开始;
		- 【4】若p的叔结点为黑色,且当前结点是其父节点的右孩子;
			- 将父节点作为新的当前结点;
			- 以新的当前结点为支点左旋;
			- 在按照情形5继续处理;
		- 【5】若p的叔结点为黑色,且当前结点时其父节点的左孩子;
			- 将父节点设为黑色;
			- 将祖父结点设为红色;
			- 以祖父结点为支点进行右旋;
 void insert_case1(node *n){
     if(n->parent == NULL)
         n->color = BLACK;
     else
         insert_case2 (n);
 }
 void insert_case2(node *n){
     if(n->parent->color == BLACK)
         return; /* 树仍旧有效*/
     else
         insert_case3 (n);
 }
 void insert_case3(node *n){
     if(uncle(n) != NULL && uncle (n)->color == RED) {
         n->parent->color = BLACK;
         uncle (n)->color = BLACK;
         grandparent (n)->color = RED;
         insert_case1(grandparent(n));
     }
     else
         insert_case4 (n);
 }
 void insert_case4(node *n){
     if(n == n->parent->right && n->parent == grandparent(n)->left) {
         rotate_left(n);
         n = n->left;
     } else if(n == n->parent->left && n->parent == grandparent(n)->right) {
         rotate_right(n);
         n = n->right;
     }
     insert_case5 (n);
 }
 void insert_case5(node *n){
     n->parent->color = BLACK;
     grandparent (n)->color = RED;
     if(n == n->parent->left && n->parent == grandparent(n)->left) {
         rotate_right(n->parent);
     } else {
         /* Here, n == n->parent->right && n->parent == grandparent (n)->right */
         rotate_left(n->parent);
     }
 }

4.4 删除

【删除操作】:x删除节点,s为x的兄弟结点


【1】x为红直接删除;
【2】x为黑色,x为根节点直接删除;
	【2.1】x有一个红色子节点:
		用红色子节点来替代被删除的节点,然后染为黑色;
    【2.2】x都为黑色结点:
		【2.2.2】s结点为黑色:
			1)s有红色子节点(借用兄弟子节点修复)
				- 子节点可能左孩子(右旋)或右孩子(先左旋再右旋)、或左右孩子(选左孩子);
				- 在删除x后,对x的父节点进行旋转,s染为红色,两个子节点染为黑色;
			2)s没有红色子节点(父结点向下合并红与黑)
				- 【若父节点为红色】:s染红,父节点染黑即可;
				- 【若父节点为黑色】:s染红,把父节点进行递归;
		【2.2.3】s为红色(转变为黑色处理)
			父节点右旋,兄弟结点染黑,父节点染红,然后使用兄弟为黑色的方法进行修复;

5 与AVL树的比较

- 与红黑树相比,AVL树提供更快的查询,由于他是更加严格的平衡即读的性能会更好;
- 红黑树提供更快的插入和删除操作,因为AVL的旋转操作更多,红黑树会更少一点,由于红黑树是一个近似平衡二叉树;
- AVL要存的额外的信息(heght)更多,需要用到更多的内存附加在每个节点,而红黑树要的信息相对较少,只需要一个bit来
判断是红还是黑即可,对额外的空间消耗更小,在百万级的结点个数;
- 若在读操作比较多,写操作少的情况就使用AVL;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Jxiepc

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

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

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

打赏作者

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

抵扣说明:

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

余额充值