ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

红黑树的实现

2021-01-18 21:58:48  阅读:220  来源: 互联网

标签:node parent 实现 bst rbtree 红黑树 color left


  1. 定义:
  • 每个结点要么是“红色”,要么是“黑色”(后面将说明)
  • 所有的叶结点都是空结点,并且是“黑色”的
  • 如果一个结点是“红色”的,那么它的两个子结点都是“黑色”的。
  • 结点到其子孙结点的每条简单路径都包含相同数目的“黑色”结点
  • 根结点永远是“黑色”的

首先,是先有红黑树,再通过无数的经验总结出来了红黑树特殊的性质。所以不必深入研究这些性质是怎么来的。

2.说明:

  • 红黑树全名平衡二叉检索树,主要应用于一些系统方面:
    • Linux进程调度 CFS
    • Nginx Timer事件管理
    • Epoll事件块的管理
  • 特性2中的叶子节点,是只为空(NIL或null)的节点。
  • 特性4,确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树。

3.左旋右旋
在这里插入图片
在这里插入图片描述

首先,上述红黑树的性质是为了对该二叉树做出一些约束让红黑树达到查询的最佳的时间复杂度,在对一个平衡的红黑树进行插入或者删除操作之后,如果违反上述红黑树的性质,导致查询的时间复杂度下降。而通过左旋和右旋来让二叉树满足性质。

1.插入
红黑树的插入必定在叶子节点上进行的。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

对应的插入节点再右子树上和上述情况刚好相反。

2.删除

  1. 当前结点的兄弟结点是红色的
  2. 当前结点的兄弟结点是黑色的,而且兄弟结点的
    两个孩子结点都是黑色的
  3. 当前结点的兄弟结点是黑色的,而且兄弟结点的
    左孩子是红色的,右孩子是黑色的
    当前结点是父结点的左子树的情况
  4. 当前结点的兄弟结点是黑色的,而且兄弟结点的
    右孩子是红色的

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

附上代码:
测试可通过,代码为C代码,但是C++编译器可通过, C编译器应该问题不大。

RbTree.h


typedef int KEY;
typedef int VALUE;
#define RED 1
#define BLACK 2

#define RBTREE_ENTRY(name, type) \
struct name{					 \
	unsigned color;				\
	struct type * parent;		\
	struct type * left;		 \
	struct type * right;		 \
}


struct rbtree_node
{
	RBTREE_ENTRY(, rbtree_node) bst;

	KEY key;
	VALUE Value;
};


struct rbtree
{
	rbtree() {
		root = NULL;
	}
	struct rbtree_node* root;
	struct rbtree_node* nil;
};

RbTree.cpp

#include "RbTree.h"



struct rbtree_node* rbtree_node_create(int key, VALUE value)
{
	struct rbtree_node* new_node = (struct rbtree_node*)malloc(sizeof(rbtree_node));
	if (NULL == new_node)
	{
		return NULL;
	}
	new_node->bst.left = NULL;
	new_node->bst.right = NULL;
	new_node->bst.parent = NULL;
	new_node->bst.color = RED;
	new_node->key = key;
	new_node->Value = value;
	return new_node;
}


rbtree_node* rbtree_successor(rbtree* T, rbtree_node* x) {
	rbtree_node* y = x->bst.parent;

	if (x->bst.right != T->nil) {
		//return rbtree_mini(T, x->bst.right);
		rbtree_node * rnode = x->bst.right;
		while (rnode->bst.left != T->nil) {
			rnode = rnode->bst.left;
		}
		return rnode;
	}

	while ((y != T->nil) && (x == y->bst.right)) {
		x = y;
		y = y->bst.parent;
	}
	return y;
}


int rbtree_left_translate(rbtree* T, rbtree_node * x)
{
	if (NULL == T || NULL == x)
	{
		return -1;
	}

	rbtree_node* y = x->bst.right;

	//1
	y->bst.parent = x->bst.parent;
	if (x->bst.parent == T->nil)
	{
		T->root = y;
	}
	else if (x == x->bst.parent->bst.left)
	{
		x->bst.parent->bst.left = y;
	}
	else
	{
		x->bst.parent->bst.right = y;
	}
	

	//3
	if (y->bst.left != T->nil)
	{
		y->bst.left->bst.parent = x;
	}
	x->bst.right = y->bst.left;


	y->bst.left = x;
	x->bst.parent = y;
	


}

int rbtree_right_translate(rbtree* T, rbtree_node* x)
{
	if (NULL == T || NULL == x)
	{
		return -1;
	}

	rbtree_node* y = x->bst.left;

	//1
	y->bst.parent = x->bst.parent;
	if (x->bst.parent == T->nil)
	{
		T->root = y;
	}
	else if (x->bst.parent->bst.left = x)
	{
		x->bst.parent->bst.left = y;
	}
	else
	{
		x->bst.parent->bst.right = y;
	}


	if (y->bst.right != T->nil)
	{
		y->bst.right->bst.parent = x;
	}
	x->bst.left = y->bst.right;

	y->bst.right = x;
	x->bst.parent = y;
	
}

// 插入一个节点之前,该红黑色必然是平衡二叉树,只有插入的当前节点(插入节点默认为红色)和父节点都为红色,破坏了二叉树的平衡, 才需要自平衡
void rbtree_insert_fixup(rbtree* T, rbtree_node* z)
{
	while (RED == z->bst.parent->bst.color)
	{
		if (z->bst.parent == z->bst.parent->bst.left)//当前插入节点在祖父节点的左子树 叔父节点祖父节点的右边
		{
			rbtree_node* y = z->bst.parent->bst.parent->bst.right;
			if (RED == y->bst.color)//叔父节点为红色
			{
				z->bst.parent->bst.color = BLACK;
				y->bst.color = BLACK;
				z->bst.parent->bst.parent->bst.color = RED;

				z = z->bst.parent->bst.parent;//改变了祖父节点的颜色,所以需要循环向上遍历是否满足性质
			}
			else//叔父节点为黑色,需要右旋
			{
				if (z == z->bst.parent->bst.right)//当前插入节点为父节点的右节点,需要先左旋
				{
					z = z->bst.parent;
					rbtree_left_translate(T, z);
				}

				z->bst.parent->bst.color = BLACK;
				z->bst.parent->bst.parent->bst.color = RED;
				rbtree_right_translate(T, z->bst.parent->bst.parent);

			}
		}
		else//当前插入节点在祖父节点的右子树
		{
			rbtree_node* y = z->bst.parent->bst.parent->bst.left;
			if (RED == y->bst.color)//叔父节点为红色
			{
				z->bst.parent->bst.color = BLACK;
				y->bst.color = BLACK;
				z->bst.parent->bst.parent->bst.color = RED;

				z = z->bst.parent->bst.parent;//改变了祖父节点的颜色,所以需要循环向上遍历是否满足性质
			}
			else//叔父节点为黑色,需要左旋
			{
				if (z == z->bst.parent->bst.left)//当前插入节点为父节点的左节点,需要先右旋
				{
					z = z->bst.parent;
					rbtree_right_translate(T, z);
				}

				z->bst.parent->bst.color = BLACK;
				z->bst.parent->bst.parent->bst.color = RED;
				rbtree_left_translate(T, z->bst.parent->bst.parent);

			}
		}

		//根节点为黑色
		T->root->bst.color = BLACK;
	}
}

void rbtree_insert(rbtree* T, rbtree_node* z) {


	rbtree_node* y = T->nil;
	rbtree_node* x = T->root;

	while (x != T->nil) {
		y = x;
		if (z->key < x->key) {
			x = x->bst.left;
		}
		else if (z->key > x->key) {
			x = x->bst.right;
		}
		else { //Exist 就退出
			return;
		}
	}

	z->bst.parent = y;
	if (y == T->nil) {
		T->root = z;
	}
	else if (z->key < y->key) {
		y->bst.left = z;
	}
	else {
		y->bst.right = z;
	}

	z->bst.left = T->nil;
	z->bst.right = T->nil;
	z->bst.color = RED;

	rbtree_insert_fixup(T, z);
}


void rbtree_delete_fixup(rbtree* T, rbtree_node* x) {

	while ((x != T->root) && (x->bst.color == BLACK)) {
		if (x == x->bst.parent->bst.left) {

			rbtree_node* w = x->bst.parent->bst.right;
			if (w->bst.color == RED) {
				w->bst.color = BLACK;
				x->bst.parent->bst.color = RED;

				rbtree_left_translate(T, x->bst.parent);
				w = x->bst.parent->bst.right;
			}

			if ((w->bst.left->bst.color == BLACK) && (w->bst.right->bst.color == BLACK)) {
				w->bst.color = RED;
				x = x->bst.parent;
			}
			else {

				if (w->bst.right->bst.color == BLACK) {
					w->bst.left->bst.color = BLACK;
					w->bst.color = RED;
					rbtree_right_translate(T, w);
					w = x->bst.parent->bst.right;
				}

				w->bst.color = x->bst.parent->bst.color;
				x->bst.parent->bst.color = BLACK;
				w->bst.right->bst.color = BLACK;
				rbtree_left_translate(T, x->bst.parent);

				x = T->root;
			}

		}
		else {

			rbtree_node* w = x->bst.parent->bst.left;
			if (w->bst.color == RED) {
				w->bst.color = BLACK;
				x->bst.parent->bst.color = RED;
				rbtree_right_translate(T, x->bst.parent);
				w = x->bst.parent->bst.left;
			}

			if ((w->bst.left->bst.color == BLACK) && (w->bst.right->bst.color == BLACK)) {
				w->bst.color = RED;
				x = x->bst.parent;
			}
			else {

				if (w->bst.left->bst.color == BLACK) {
					w->bst.right->bst.color = BLACK;
					w->bst.color = RED;
					rbtree_left_translate(T, w);
					w = x->bst.parent->bst.left;
				}

				w->bst.color = x->bst.parent->bst.color;
				x->bst.parent->bst.color = BLACK;
				w->bst.left->bst.color = BLACK;
				rbtree_right_translate(T, x->bst.parent);

				x = T->root;
			}

		}
	}

	x->bst.color = BLACK;
}



rbtree_node* rbtree_delete(rbtree* T, rbtree_node* z) {

	rbtree_node* y = T->nil;
	rbtree_node* x = T->nil;

	if ((z->bst.left == T->nil) || (z->bst.right == T->nil)) {
		y = z;
	}
	else {
		y = rbtree_successor(T, z);
	}

	if (y->bst.left != T->nil) {
		x = y->bst.left;
	}
	else if (y->bst.right != T->nil) {
		x = y->bst.right;
	}

	x->bst.parent = y->bst.parent;
	if (y->bst.parent == T->nil) {
		T->root = x;
	}
	else if (y == y->bst.parent->bst.left) {
		y->bst.parent->bst.left = x;
	}
	else {
		y->bst.parent->bst.right = x;
	}

	if (y != z) {
		z->key = y->key;
		z->Value = y->Value;
	}

	if (y->bst.color == BLACK) {
		rbtree_delete_fixup(T, x);
	}

	return y;
}

标签:node,parent,实现,bst,rbtree,红黑树,color,left
来源: https://blog.csdn.net/qq_41949110/article/details/112793328

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有