【数据结构】红黑树定义及基本操作

红黑树

红黑树基础定义

  1. 二叉搜索树,每个节点要么是黑节点,要么是红节点
  2. 每个节点到下面叶子节点的所有路径中,黑色节点的数量都相等
  3. 红色节点的子节点一定是黑色节点
  4. 根节点是黑色节点
  5. 叶子节点全是黑色节点。

其C语言的结构体定义如下

c 复制代码
typedef struct _rbtree_node {
	int key;
	void *val;
	
	struct _rbtree_node *parent;
	struct _rbtree_node *left;
	struct _rbtree_node *right;
	char color;
} rbtree_node;

typedef struct _rbtree {
	struct _rbtree_node *root;
	struct _rbtree_node *nil;  // 需要生成一个通用的黑色叶子节点,代表空,避免复杂的边界null处理
} rbtree;

红黑树插入新节点

红黑树左旋和右旋

红黑树的插入操作,需要定义左旋和右旋的操作。

从上图可以看出,左旋和右旋是可逆的操作,且不会改变节点的颜色。

  • 左旋代码(只有核心操作代码)
c 复制代码
void rbtree_left_rotation(rbtree *T, rbtree_node *x)
{
	
	rbtree_node *y = x->right;
	// 先把b节点放到x的右节点上
	x->right = y->left;
	if (y->left != T->nil) {
		y->left->parent = x;
	}
	
	// 再把y节点接到x的父节点上
	if (x->parent == T->nil) { // 此时x为根节点,所以parent是空
		T->root = y;
	} else if (x->parent-left == x) {
		x->parent->left = y;
	} else {
		x->parent->right = y;
	}
	y->parent = x->parent;

	// 再把x放到y的左节点上
	x->parent = y;
	y->left = x;
	
}
  • 右旋代码(把左旋代码中的x和y对调, left和right对调即可)
c 复制代码
void rbtree_right_rotation(rbtree *T, rbtree_node *y)
{
	rbtree_node *x = y->left;
	// 先把b节点放到y的左节点上
	y->left = x->right;
	if (x->right != T->nil) {
		x->right->parent = y;
	}
	
	// 再把x节点接到y的父节点上
	if (y->parent == T->nil) { // 此时x为根节点,所以parent是空
		T->root = x;
	} else if (y->parent-right == x) {
		y->parent->right = x;
	} else {
		y->parent->left = x;
	}
	x->parent = y->parent;

	// 再把y放到x的右节点上
	y->parent = x;
	x->right = y;
	
}
  • 插入代码
c 复制代码
void rbtree_insert_fixup(rbtree *T, rbtree_node *z)
{
	while (z->parent->color == RED) {
		if (z->parent == z->parent->parent->left) {
			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;
			} else {
				if (z == z->parent->right) {
					z = z->parent;
					rbtree_left_rotation(T, z);
				}
				
				z->parent->color = BLACK;
				z->parent->parent->color= RED;
				rbtree_right_rotation(T, z->parent);
				
			}
		}
		
	}

}

void rbtree_insert(rbtree *T, rbtree_node *z)
{
	rbtree_node *x = T->root;
	btree_node *y = T->nil;
	while (x != T->nil) {
		y = x;
		if (z->key < x->key) {
			x = x->left;
		} else if (z->key > x->key) {
			x = x->right;
		} else {
			return;
		}
	}

	if (y == T->nil) {
		T->root = z;
		return;
	}

	if (z->key > y->key) {
		y->right = z;
	} else {
		y->left = z;
	}
	z->parent = y;

	z->color = RED;
	rbtree_insert_fixup(T, z);
}
相关推荐
努力努力再努力wz7 分钟前
【Linux网络系列】万字硬核解析网络层核心:IP协议到IP 分片重组、NAT技术及 RIP/OSPF 动态路由全景
java·linux·运维·服务器·数据结构·c++·python
谭欣辰2 小时前
AC自动机:多模式匹配的高效利器
数据结构·c++·算法
历程里程碑2 小时前
MySQL事务深度解析:ACID到MVCC实战+万字长文解析
开发语言·数据结构·数据库·c++·sql·mysql·排序算法
qiqsevenqiqiqiqi3 小时前
MC0550鱼肠剑试锋芒
数据结构·算法
仍然.3 小时前
算法题目---链表
数据结构·算法·链表
周末也要写八哥4 小时前
最长递增子序列典型应用题目详解
数据结构·算法
iiiiyu4 小时前
常用API(StringJoiner类 & Math类 & System类)
java·大数据·开发语言·数据结构·编程语言
小糯米6014 小时前
C语言指针3
c语言·数据结构·算法
见叶之秋5 小时前
【数据结构】二叉树的遍历和节点个数
数据结构
澈2075 小时前
高效查找算法详解:从顺序到哈希
数据结构·算法·哈希算法