第13章 红黑树

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<queue>
#define RED 1
#define BLACK 0
using namespace std;
struct node{
	int color;
	int key;
	node* left;
	node* right;
	node* parent;
};

//左旋
void leftRotate(node* &root, node* x)
{
	node* y = x->right;
	if (x->right = y->left) y->left->parent = x;
	if (y->parent = x->parent){
		if (x == x->parent->left) x->parent->left = y;
		else x->parent->right = y;
	}
	else root = y;
	x->parent = y;
	y->left = x;
}
//右旋(x-y,left-right)
void rightRotate(node* &root, node* y)
{
	node* x = y->left;
	if (y->left = x->right) x->right->parent = y;
	if (x->parent = y->parent){
		if (y = y->parent->right) y->parent->right = x;
		else y->parent->left = x;
	}
	else root = x;
	y->parent = x;
	x->right = y;
}
void RBinsertFixup(node* &root, node* z)
{
	while (z->parent && z->parent->color == RED){
		if (z->parent == z->parent->parent->left){	//父节点为左支
			node* y = z->parent->parent->right;
			if (y&&y->color == RED){					//case 1:父节点及其兄弟节点为RED。处理如下:
				z->parent->color = BLACK;						//父节点及其兄弟节点变为BLACK
				y->color = BLACK;
				y->parent->color = RED;							//祖父节点变为RED
				z = y->parent;									//将祖父节点变为当前节点 z
			}
			else{
				if (z == z->parent->right){				//case 2:父节点为RED,叔叔节点为BLACK,且 z 为父节点的右子节点。处理如下:
					z = z->parent;								//对父节点进行左旋操作,使之成为 case 3
					leftRotate(root, z);
				}
														//case 3:父节点为RED,叔叔节点为BLACK,且 z 为父节点的左子节点。处理如下:
				z->parent->color = BLACK;						//父节点变为 BLACK
				z->parent->parent->color = RED;					//祖父节点变为 RED
				rightRotate(root, z->parent->parent);			//对祖父节点进行右旋
			}
		}
		else{										//父节点为右支
			node *y = z->parent->parent->left;
			if (y&&y->color == RED){
				z->parent->color = BLACK;
				y->color = BLACK;
				y->parent->color = RED;
				z = y->parent;
			}
			else{
				if (z == z->parent->left){
					z = z->parent;
					rightRotate(root, z);
				}

				z->parent->color = BLACK;
				z->parent->parent->color = RED;
				leftRotate(root, z->parent->parent);
			}
		}
	}
	root->color = BLACK;
}
void RBinsert(node* &root, int val)
{
	node* z = (node*)malloc(sizeof(node));
	node *y = NULL, *x = root;
	while (x){
		y = x;
		if (x->key > val) x = x->left;
		else if (x->key < val) x = x->right;
		else return;
	}
	z->parent = y;
	if (y == NULL) root = z;
	else if (y->key > val) y->left = z;
	else y->right = z;
	z->left = z->right = NULL;
	z->key = val;
	z->color = RED;
	RBinsertFixup(root, z);
}
void RBtransplant(node* &root, node* u, node* v)
{
	if (u->parent == NULL) root = v;
	else if (u == u->parent->left) u->parent->left = v;
	else u->parent->right = v;
	if (v) v->parent = u->parent;
}
void RBdeleteFixup(node* &root, node* x,node* p_x)
{
	node *w;								// x 的父节点的兄弟节点
	while ((!x || x->color == BLACK) && x != root){
		if (x == p_x->left){				// x 的父节点为祖父节点的左支
			w = p_x->right;
			if (w->color == RED){				//case 1: w 是 RED,通过左旋,使之成为 case 2,3,4:
				w->color = BLACK;
				p_x->color = RED;
				leftRotate(root, p_x);
				w = p_x->right;
			}
			if ((w->left == NULL || w->left->color == BLACK) && (w->right == NULL || w->right->color == BLACK)){
				w->color = RED;					//case 2: w 是 BLACK, 左 BLACK 右 BLACK
				x = p_x;
				p_x = p_x->parent;
			}
			else{
				if (w->right == NULL || w->right->color == BLACK){
					if (w->left) w->left->color = BLACK;		//case 3: w 是 BLACK, 左 RED 右 BLACK
					w->color = RED;
					rightRotate(root, w);
					w = p_x->right;
				}
				w->color = p_x->color;							//case 4: w 是 BLACK, 右 RED
				p_x->color = BLACK;
				if (w->right) w->right->color = BLACK;
				leftRotate(root, p_x);
				break;
			}
		}
		else{								// x 的父节点为祖父节点的右支
			w = p_x->left;
			if (w->color == RED){
				w->color = BLACK;
				p_x->color = RED;
				rightRotate(root, p_x);
				w = p_x->left;
			}
			if ((w->left == NULL || w->left->color == BLACK) && (w->right == NULL || w->right->color == BLACK)){
				w->color = RED;
				x = p_x;
			}
			else{
				if (w->left == NULL || w->left->color == BLACK){
					if (w->right) w->right->color = BLACK;
					w->color = RED;
					leftRotate(root, w);
					w = p_x->left;
				}
				w->color = p_x->color;
				p_x->color = BLACK;
				if (w->left) w->left->color = BLACK;
				rightRotate(root, p_x);
				break;
			}
		}
	}
	if (x) x->color = BLACK;
}
node* RBdelete(node* &root, int val)
{
	node* z = root;
	while (z){
		if (z->key > val) z = z->left;
		else if (z->key < val) z = z->right;
		else break;
	}
	if (z == NULL) return NULL;
	node* y = z, *x, *p_x;
	int colory = y->color;
	if (z->left == NULL){
		x = z->right;
		p_x = z->parent;
		RBtransplant(root, z, z->right);
	}
	else if (z->right == NULL){
		x = z->left;
		p_x = z->parent;
		RBtransplant(root, z, z->left);
	}
	else{
		y = z->right;
		while (y->left) y = y->left;
		colory = y->color;
		x = y->right;
		p_x = y->parent;
		z->key = y->key;
		RBtransplant(root, y, y->right);
	}
	free(y);
	if (colory == BLACK){
		RBdeleteFixup(root, x, p_x);
	}
	return x;
}
void printRB(node* root)
{
	node *p;
	queue<node*> q;
	q.push(root);
	while (!q.empty()){
		p = q.front(); q.pop();
		if (p){
			printf("%d", p->key);
			if (p->color == RED) printf("r ");
			else printf("b ");
			q.push(p->left);
			q.push(p->right);
		}
		else printf("- ");
	}
	printf("\n");
}
int main()
{
	int a[] = { 11, 3, 14, 1, 7, 15, 5, 8, 4 };
	for (int j = 1; j < 10; ++j){
		node* root = NULL;
		for (int i = 0; i < j; ++i)
			RBinsert(root, a[i]);
		printRB(root);
	}
	printf("\n\n");
	for (int k = 0; k < 9; ++k){
		node* root = NULL;
		for (int i = 0; i < 9; ++i)
			RBinsert(root, a[i]);
		node* x=RBdelete(root, a[k]);
		printRB(root);
	}

}

  

时间: 2025-01-11 17:20:10

第13章 红黑树的相关文章

【算法导论】学习笔记——第13章 红黑树

红黑树(red-black tree)是许多平衡搜索树中的一种,因此基本操作(查询.删除.搜索)等在最坏情况下的时间复杂度均为O(lgn).13. 1 红黑树的性质红黑树时一棵二叉搜索树,并且在每个结点上增加了一个属性表示颜色:红色或黑色.通过对任何一条从根到叶子的简单路径上各个结点的颜色进行约束,红黑树确保没有一条路径会比其它路径长出2倍.因而是近似于平衡的.一棵红黑树是满足下面红黑性质的二叉搜索树:1. 每个结点是红色或黑色:2. 根结点是黑色的:3. 每个叶结点(NIL)是黑色的:4. 如

算法导论 第13章 红黑树

二叉查找树的基本操作包括搜索.插入.删除.取最大和最小值等都能够在O(h)时间复杂度内实现,因此能在期望时间O(lgn)下实现,但是二叉查找树的平衡性在这些操作中并没有得到维护,因此其高度可能会变得很高,当其高度较高时,而二叉查找树的性能就未必比链表好了,所以二叉查找树的集合操作是期望时间O(lgn),最坏情况下为O(n). 红黑树也是一种二叉查找树,它拥有二叉查找树的性质,同时红黑树还有其它一些特殊性质,这使得红黑树的动态集合基本操作在最坏情况下也为O(lgn),红黑树通过给节点增加颜色和其它

算法导论学习笔记——第13章 红黑树

红黑树 红黑树是一种二叉查找树,但在每个结点上增加一个存储位存储结点的颜色,可以是red或black.通过对任意一条从根到叶的路径上结点颜色的限制,红黑树确保没有任何一条路径比其他路径长出两倍,因而是接近平衡的. 每个结点包含5个域,color,key,left,right,p 满足以下红黑性质: 1.每个结点是红色或黑色 2.根结点是黑色 3.每个叶结点(nil)是黑色 4.如果一个结点是红色,那么它的两个子结点都是黑色 5.对每个结点,从该结点到它每个子孙结点的路径上,黑结点数目相同 左旋转

第09章 红黑树

红黑树 红黑树是一种二进制查找树,但在每个节点上增加一个存储位表示节点的颜色,可以是red或black.通过对任何一条从根到叶子的路径上各个节点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的. 树中灭个节点包含五个域,color,key,left,right 和p.如果某及诶但没有一个子节点或父节点,则该节点响应的指针域包含值NIL.我们将把这些NIL指向二叉查找树的外节点(叶子)指针,而把带关键字的节点,视为树的内节点. 一棵二进制查找树如果满足以下性质,则说明是

算法导论第十三章 红黑树

写在前面:这一章真的把我害惨了,之前至少尝试看过3遍,每次看之前都下定决定一定要把它拿下,可是由于内容较多,深度够深,以致于每次要不是中途有什么事放弃了就跳过了,要不是花时间太多仍然不能理解而放弃.这次总算挺过来了,前后零零散散的时间加起来差不多也有两天时间.这次能坚持下来并攻克,我想大概有这么几个原因吧:第一是之前下定的决心要写一个最新版<算法导论>的读书笔记,之前几章都坚持写了,不能让这个成为拦路虎,即使再难再花时间都要弄懂:第二是通过前面几章的动手实践,发现自己的理解能力.动手能力都进步

算法导论 第十三章 红黑树(python)-1插入

红黑树是上一章二叉搜索树的改进,实现一种平衡 ,保证不会出现二叉树变链表的情况,基本动态集合操作的时间复杂度为O(lgn) 实际用途:c++stl中的set,map是用他实现的 红黑树的性质: 1.每个结点或是红色的,或是黑色的 2.跟结点是黑色的 3.每个叶结点(NIL)是黑色 4.如果一个结点是红色的,则它的两个结点都是黑色的 5.对每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同的数目的黑色结点(数目被称为黑高bh(x)) 如下图: (T.nil 哨兵后面被忽略 None) 红

第十四章 红黑树——C++代码实现

红黑树的介绍 红黑树(Red-Black Tree,简称R-B Tree),它一种特殊的二叉查找树.红黑树是特殊的二叉查找树,意味着它满足二叉查找树的特征:任意一个节点所包含的键值,大于等于左孩子的键值,小于等于右孩子的键值.除了具备该特性之外,红黑树还包括许多额外的信息. 红黑树的每个节点上都有存储位表示节点的颜色,颜色是红(Red)或黑(Black).红黑树的特性:(1) 每个节点或者是黑色,或者是红色.(2) 根节点是黑色.(3) 每个叶子节点是黑色. [注意:这里叶子节点,是指为空的叶子

第十三章 红黑树

R-B Tree简介 R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树.红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black). 红黑树的特性:(1)每个节点或者是黑色,或者是红色.(2)根节点是黑色.(3)每个叶子节点(NIL)是黑色. [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!](4)如果一个节点是红色的,则它的子节点必须是黑色的.(5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点.

java数据结构和算法-----第九章红黑树

平衡树和非平衡树 如果待插入的关键字是升序的或者降序的,将会产生非平衡树.(都只在根节点的左边或者右边) 当树没有分支时,此时的树就可以看做单链表.