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

红黑树

红黑树基础定义

  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);
}
相关推荐
CS创新实验室23 分钟前
从顺序表到动态数组:数据结构的永恒基石与现代语言的优雅封装
数据结构·算法
8Qi82 小时前
LeetCode 23. 合并 K 个升序链表 —— 小顶堆(PriorityQueue)
数据结构·算法·leetcode·链表·
QiLinkOS2 小时前
《打破“用爱发电”:一种基于 Gitee 与时间戳的开源权益分配机制探索》
c语言·数据结构·c++·科技·算法·gitee·开源
Boom_Shu4 小时前
长方形的关系
数据结构·c++·算法
Lsk_Smion5 小时前
力扣实训 _ [543].二叉树的直径 _ [23].合并K个升序列表
数据结构·算法·leetcode
ID_180079054738 小时前
淘宝商品详情数据接口深度解析:架构、鉴权、数据结构与实战
数据结构·架构
散峰而望8 小时前
【算法练习】算法练习精选:陶陶摘苹果(基础+升级)、Music Notes、字串变换,你能AC几道?
数据结构·c++·算法·leetcode·贪心算法·github·动态规划
凤凰院凶涛QAQ9 小时前
《Java版数据结构 & 集合类剖析》集合框架的封装设计与顺序表:“从 Iterable 到 ArrayList:集合框架的‘职业树“
java·开发语言·数据结构
8Qi89 小时前
LeetCode 148. 排序链表 —— 解法一:自顶向下递归(分治 + 归并)
数据结构·算法·leetcode·链表·递归·分治·归并
8Qi89 小时前
LeetCode 148. 排序链表 —— 解法二:自底向上归并(迭代,O(1) 空间)
数据结构·算法·leetcode·链表·归并·迭代