数据结构与算法:随处可见的红黑树

1.红黑树工程实用的特点

  1. 查找效率高:通过key可以找到与之对应的value,查找的时间复杂度为O(log~2~N).比如:epoll中对事件管理是通过红黑树来管理的,通过查找fd可以快速的找到与之对应的事件。与之相似的强查找过程的数据结构还有:rbtree、hashmap(时间复杂度O(1),效率最高)、B\B+树、跳表等。
  2. 中序遍历是有序的,可以用于筛选:比如:Timer定时器中判断定时器是否超时,在红黑树中找到一个小于或等于超时时间的定时器节点,那么这个节点左子树上的所有定时器节点都是超时的。

2.红黑树的应用场景(进程调度CFS、内存管理)

2.1 Linux进程调度CFS

2.2 Nginx Timer 事件管理

2.3 Epoll 事件块管理

3.红黑树的定义

判别一棵树是否为黑红黑树,要满足以下特点:

  1. 每个节点是红的或者黑的
  2. 根节点是黑的
  3. 每个叶子节点是黑的
  4. 如果一个节点是红的,则它的两个儿子都是黑的
  5. 对于每个节点,从该节点到其子孙节点的所有路径上的包含相同数目的黑节点

红黑树的鉴定
  注意所有的叶子节点都是隐藏的,并且为黑色,在编程的时候为了方便管理所有的叶子节点,可以将所有的叶子节点指向同一个为空的节点,上图中只有图2满足红黑树的所有特点。

4.红黑树的左旋和右旋

  旋转:当红黑树的性质被破坏的时候,此时需要对红黑树进行调整。对红黑树的调整包括:旋转与变色,左旋与右旋是一个可逆的过程。
红黑树的左旋和右旋
左旋与右旋代码实现:

//b节点有两种情况:1.b为叶子节点 2.b不是叶子节点
//x有三种情况:1.x为根节点 2.x为x->parent的左孩子 3.x为x->parent的右孩子
void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
   
	rbtree_node *y = x->right;
	
	x->right = y->left;
	if(y->left != T->nil)	//b不是叶子节点
		y->left->parent = x;
	//x有三种情况:	
	y->parent = x->parent;
	if(x->parent == T->nil){
   	//x为根节点
		T->root = y;
	}else if(T->left = x){
   		//x为x->parent的左孩子
		x->parent->left = y;
	}else{
   						//x为x->parent的右孩子
		x->parent->right = y;
	}
	
	x->parent = y;
	y->left = x;
}
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;
}

5.红黑树添加一个新节点的三种情况

  要添加一个新节点,新节点的初始颜色置为红色还是黑色? ** 红色**

插入的新节点是颜色是红色的好处:
  1. 不会改变黑高,如果插入新节点的父节点的颜色为黑色,直接插入即可,不需要对红黑树进行调整。
  2. 判断红黑树是否需要调整只需要判断新节点z的父节点的颜色是否为红色即可。如果需要调整能够推测出:z的颜色是红色的、z的父节点的颜色是红色的、z的祖父节点的颜色是黑色的、z的叔父节点的颜色不确定。可以是红色的也可以是黑色的,这个是对后面红黑树调整的判断条件。

5.1 父节点是祖父节点的左子树的情况

  插入一个新节点首先需要遍历红黑树,查找一个合适的插入位置,并且插入的新节点的颜色是红色的。如果破坏了红黑树的特性在对红黑树进行调整,下面是在红黑树找到一个合适的节点插入新节点的代码:

void rbtree_insert(rbtree *T, rbtree_node *z) {
   
	retree_node *x = T->root;
	retree_node *y = T->root;
	//找到将要插入新节点z的父节点y
	while(x == T->nil){
   
		y = x;
		if(z->key < x->key){
   
			x = x->left;
		}else{
   
			x = x->right;
		}
	}
	z->parent = y;
	//判断z是y的左孩子还是右孩子
	if(y == T->nil){
   
		T->root = z;
	}else if(z->key < y->key){
   
		y->left = z;
	}else{
   
		y->right = z;
	}
	z->left = T->nil;
	z->right = T->nil;
	e->color = RED;
	//对红黑树进行调整
	rbtree_insert_fixup(T, z);
}

5.1.1 叔节点是红色的

  插入的新节点z的叔父节点是红色的,对红黑树进行调整只需要将z的父节点与叔父节点的颜色由红色变成黑色,将z的祖父节点的颜色由黑色变成红色,最后,再将z的祖父节点赋值给z
树节点是红色的

5.1.2 叔节点是黑色的,而且当前节点是右孩子

  这是由叔父节点是红色调整之后得到的新情况:叔父节点是黑色的,而且当前节点是右孩子。需要对红黑树进行调整:先将z父节点赋值给z,再对z进行左旋,可以得到下一种情况:叔父节点是黑色的,而且当前节点是右孩子。
树节点是黑色的,而且当前节点是右孩子

5.1.3 叔节点是黑色的,而且当前节点是左孩子

  这是由树父节点的黑色的,而且当前节点是右孩子,经过左旋得到的新情况。需要对红黑树进行调整:变色:将z的父节点的颜色由红色变成黑色,将z的祖父节点有黑色变成红色。旋转:以z的祖父节点进行右旋。
树节点是黑色的,而且当前节点是左孩子

void rbtree_insert_fixup(rbtree *T, rbtree_node *z
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
数据结构与算法分析:C语言描述清晰版》是由美国著名计算机科学家Mark Allen Weiss所著,是一本介绍数据结构和算法的经典教材之一。该书内容丰富、深入浅出,既有基础知识的讲解,也有高级算法的探讨,适合计算机科学及其他相关专业的学生、计算机编程爱好者、程序员等人群。 本书主要内容包括线性结构、递归、树、排序和搜索算法、散列表、图等多个章节。其中,线性结构是数据结构的基础,包括线性表、栈、队列等数据结构的实现和操作。递归是一种特殊的函数调用方式,在算法设计中应用广泛,本书详细讲解了递归的原理和应用。树是一种重要的非线性数据结构,本书介绍了二叉树、堆、AVL树等多种树形结构的实现和应用。排序和搜索算法是解决各种实际问题的重要工具,本书详细讲解了冒泡排序、插入排序、归并排序、快速排序等多种排序算法及二分查找、哈希表查找等多种搜索算法。散列表是一种实现高效查找的数据结构,本书深入浅出地讲解了散列表的实现原理和应用。图是一种复杂的数据结构,在算法设计中具有很高的应用价值,本书介绍了图的表示方法、遍历方法和最短路径算法等多个方面的内容。 总的来说,《数据结构与算法分析:C语言描述清晰版》是一本综合性的计算机科学教材,既适合初学者入门学习,也适合中高级程序员深入研究。本书内容翔实,全面而深入,不仅介绍了数据结构和算法的基本知识,还讲解了实践中的应用技巧和注意事项,对于从事计算机科学相关领域的人员来说,具有很高的实用价值和参考意义。如果你想在数据结构和算法方面有更深入的了解,那么这本书绝对是你不可错过的参考资料。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值