红黑树的实现与应用

本文深入探讨红黑树的数据结构及其在平衡二叉查找树中的应用,通过具体代码实现红黑树的插入、查找与删除操作,并分析其在算法效率上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

正如这篇博文中说到的金山网络面试经历  http://blog.youkuaiyun.com/huruzun/article/details/24634593  面试官要自己设计数据结构实现容器类,需要尽快的实现插入删除查找,在现实实现STL 容器类中红黑树被广泛的应用。

平衡二叉树(BalancedBinary Tree或Height-Balanced Tree)又称AVL树。它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。若将二叉树上结点的平衡因子BF(BalanceFactor)定义为该结点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有结点的平衡因子只可能是-1、0和1。(此段定义来自严蔚敏的《数据结构(C语言版)》)

红黑树严格意义上不满足平衡因子绝对值小于等于1情况,下面代码就进行测试。

我们知道一颗高度为h的二叉查找树可以实现任何一种基本的动态集合操作,其时间复杂度为 O(h)。这样在树高度比较低时,基本动态操作如插入、删除 会执行的很快,但是当树的高度较高是,尤其是极端情况下的树结构 退化成链表插入删除效率。如上面所说红黑树是许多“平衡的”的查找树中一种,它能保证在最坏情况下,基本动态集合操作的时间为 O(lgn)n 为树结点数目。

本文代码实现参考下面两篇博文感谢作者:http://blog.youkuaiyun.com/npy_lp/article/details/7420689

http://blog.youkuaiyun.com/v_JULY_v/article/details/6114226    JULY 博客强力推荐,他对算法理解很好。

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>

using namespace std;
typedef int key_t;
typedef int data_t;

typedef enum color_t
{
	RED = 0,
	BLACK = 1
}color_t;

typedef struct rb_node_t
{
	struct rb_node_t *left, *right, *parent;
	key_t key;
	data_t data;
	color_t color;
}rb_node_t;


/* forward declaration */
rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root);
rb_node_t* rb_search(key_t key, rb_node_t* root);
rb_node_t* rb_erase(key_t key, rb_node_t* root);

static rb_node_t* rb_rotate_left(rb_node_t* node, rb_node_t* root)
{

	rb_node_t* right = node->right;
	if ((node->right = right->left))//注意括号里面只是一个等号
	{
		right->left->parent = node;
	}
	right->left = node;
	if ((right->parent = node->parent))
	{
		if (node == node->parent->right)
		{
			node->parent->right = right;
		}
		else
		{
			node->parent->left = right;
		}
	}
	else
	{
		root = right;
	}
	node->parent = right;
	return root;
}


static rb_node_t* rb_rotate_right(rb_node_t* node, rb_node_t* root)
{
	rb_node_t* left = node->left;
	if ((node->left = left->right))
	{
		left->right->parent = node;
	}
	left->right = node;
	if ((left->parent = node->parent))
	{
		if (node == node->parent->right)
		{
			node->parent->right = left;
		}
		else
		{
			node->parent->left = left;
		}
	}
	else
	{
		root = left;
	}
	node->parent = left;
	return root;
}


static rb_node_t* rb_insert_rebalance(rb_node_t *node, rb_node_t *root)
{
	rb_node_t *parent, *gparent, *uncle, *tmp;
	//循环大的控制条件是 node 的 parent 颜色是红色才进入循环处理
	while ((parent = node->parent) && parent->color == RED)
	{
		gparent = parent->parent;
		if (parent == gparent->left)
		{
			uncle = gparent->right;//情况 1 node的叔叔是红色的情况
			if (uncle && uncle->color == RED)
			{
				uncle->color = BLACK;
				parent->color = BLACK;
				gparent->color = RED;
				node = gparent;
			}//情况 2 ,3 node 的叔叔是黑色的
			else
			{
				//情况 2 node 是parent的右孩子 
				if (parent->right == node)
				{
					root = rb_rotate_left(parent, root);
					// 左旋过后 交换 parent与node 位置
					tmp = parent;
					parent = node;
					node = tmp;
				}
				//情况 3 node 是parent的左孩子 
				parent->color = BLACK;
				gparent->color = RED;
				root = rb_rotate_right(gparent, root);
			}
		}
		// 算法导论中写道 :same as then with "right" and "left" exchanged 下面代码实现类似,只是把left换成 right
		else
		{
			uncle = gparent->left;
			if (uncle && uncle->color == RED)
			{
				uncle->color = BLACK;
				parent->color = BLACK;
				gparent->color = RED;
				node = gparent;
			}
			else
			{
				if (parent->left == node)
				{
					root = rb_rotate_right(parent, root);
					tmp = parent;
					parent = node;
					node = tmp;
				}
				parent->color = BLACK;
				gparent->color = RED;
				root = rb_rotate_left(gparent, root);
			}
		}
	}
	root->color = BLACK;
	return root;
}

static rb_node_t* rb_new_node(key_t key, data_t data)
{
	rb_node_t *node = (rb_node_t*)malloc(sizeof(struct rb_node_t));
	if (!node)
	{
		printf("malloc error!\n");
		exit(-1);
	}
	node->key = key, node->data = data;
	return node;
}

static rb_node_t* rb_search_auxiliary(key_t key, rb_node_t* root, rb_node_t** save)
{
	rb_node_t *node = root, *parent = NULL;
	int ret;
	while (node)
	{
		parent = node;
		ret = node->key - key;
		if (0 < ret)
		{
			node = node->left;
		}
		else if (0 > ret)
		{
			node = node->right;
		}
		else
		{
			return node;
		}
	}
	if (save)
	{
		*save = parent;
	}
	return NULL;
}

rb_node_t* rb_insert(key_t key, data_t data, rb_node_t* root)
{
	rb_node_t *parent = NULL, *node;
	parent = NULL;
	if ((node = rb_search_auxiliary(key, root, &parent)))//函数返回node需要插入的位置,并且更新parent为node的parent
	{
		return root;//node 已经存在情况直接返回
	}
	node = rb_new_node(key, data);//产生新结点函数,更好实现模块化
	//新插入节点left right 指向NULL ,颜色给成红色
	node->parent = parent;
	node->left = node->right = NULL;
	node->color = RED;
	// 使得parent 指向 node结点
	if (parent)
	{
		if (parent->key > key)
		{
			parent->left = node;
		}
		else
		{
			parent->right = node;
		}
	}
	else
	{
		root = node;
	}
	return rb_insert_rebalance(node, root);
}

rb_node_t* rb_search(key_t key, rb_node_t* root)
{
	return rb_search_auxiliary(key, root, NULL);
}

static rb_node_t* rb_erase_rebalance(rb_node_t *node, rb_node_t *parent, rb_node_t *root)
{
	rb_node_t *other, *o_left, *o_right;
	while ((!node || node->color == BLACK) && node != root)
	{
		if (parent->left == node)
		{
			other = parent->right;
			if (other->color == RED)
			{
				other->color = BLACK;
				parent->color = RED;
				root = rb_rotate_left(parent, root);
				other = parent->right;
			}
			if ((!other->left || other->left->color == BLACK) &&
				(!other->right || other->right->color == BLACK))
			{
				other->color = RED;
				node = parent;
				parent = node->parent;
			}
			else
			{
				if (!other->right || other->right->color == BLACK)
				{
					if ((o_left = other->left))
					{
						o_left->color = BLACK;
					}
					other->color = RED;
					root = rb_rotate_right(other, root);
					other = parent->right;
				}
				other->color = parent->color;
				parent->color = BLACK;
				if (other->right)
				{
					other->right->color = BLACK;
				}
				root = rb_rotate_left(parent, root);
				node = root;
				break;
			}
		}
		else
		{
			other = parent->left;
			if (other->color == RED)
			{
				other->color = BLACK;
				parent->color = RED;
				root = rb_rotate_right(parent, root);
				other = parent->left;
			}
			if ((!other->left || other->left->color == BLACK) &&
				(!other->right || other->right->color == BLACK))
			{
				other->color = RED;
				node = parent;
				parent = node->parent;
			}
			else
			{
				if (!other->left || other->left->color == BLACK)
				{
					if ((o_right = other->right))
					{
						o_right->color = BLACK;
					}
					other->color = RED;
					root = rb_rotate_left(other, root);
					other = parent->left;
				}
				other->color = parent->color;
				parent->color = BLACK;
				if (other->left)
				{
					other->left->color = BLACK;
				}
				root = rb_rotate_right(parent, root);
				node = root;
				break;
			}
		}
	}
	if (node)
	{
		node->color = BLACK;
	}
	return root;
}


rb_node_t* rb_erase(key_t key, rb_node_t *root)
{
	rb_node_t *child, *parent, *old, *left, *node;
	color_t color;
	//先查找删除结点值是否存在
	if (!(node = rb_search_auxiliary(key, root, NULL)))
	{
		printf("key %d is not exist!\n");
		return root;
	}
	old = node;
	if (node->left && node->right)
	{
		node = node->right;
		while ((left = node->left) != NULL)
		{
			node = left;
		}
		child = node->right;
		parent = node->parent;
		color = node->color;
		if (child)
		{
			child->parent = parent;
		}
		if (parent)
		{
			if (parent->left == node)
			{
				parent->left = child;
			}
			else
			{
				parent->right = child;
			}
		}
		else
		{
			root = child;
		}
		if (node->parent == old)
		{
			parent = node;
		}
		node->parent = old->parent;
		node->color = old->color;
		node->right = old->right;
		node->left = old->left;
		if (old->parent)
		{
			if (old->parent->left == old)
			{
				old->parent->left = node;
			}
			else
			{
				old->parent->right = node;
			}
		}
		else
		{
			root = node;
		}
		old->left->parent = node;
		if (old->right)
		{
			old->right->parent = node;
		}
	}
	else
	{
		if (!node->left)
		{
			child = node->right;
		}
		else if (!node->right)
		{
			child = node->left;
		}
		parent = node->parent;
		color = node->color;
		if (child)
		{
			child->parent = parent;
		}
		if (parent)
		{
			if (parent->left == node)
			{
				parent->left = child;
			}
			else
			{
				parent->right = child;
			}
		}
		else
		{
			root = child;
		}
	}
	free(old);
	if (color == BLACK)
	{
		root = rb_erase_rebalance(child, parent, root);
	}
	return root;
}
void inorder(rb_node_t *root)
{
	if (root!=NULL)
	{
		inorder(root->left);
		cout<<"key="<<root->key<<" color="<<root->color<<endl;
		inorder(root->right);
	}
}

int main()
{

	int test[6]={41,38,31,12,19,8};
	rb_node_t* root = NULL, *node = NULL;
	int i;
	for (i=0;i<6;i++)
	{
		if ((root = rb_insert(test[i], i, root)))
		{
			printf("[i = %d] insert key %d success!\n", i+1, test[i]);
		}
		else
		{
			printf("[i = %d] insert key %d error!\n", i+1, test[i]);
			exit(-1);
		}
	}
	inorder(root);

	return 0;
}



main 函数测试了算法导论给的思考题。
如果读者不理解算法过程可以参考算法导论或者JULY博文:http://blog.youkuaiyun.com/v_JULY_v/article/details/6109153

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值