红黑树的实现

学了一下算法导论上的红黑树,这个数据结构基于二叉搜索树,二叉搜索树有一个缺点:如果数据以递增的顺序插入,得到的树深度就是n,进行操作就很不方便。红黑树就是在此基础上完善,自己可以自平衡,使两边始终保持接近,这样时间复杂度就降到O(lgn)。这个数据结构的确很难,插入和删除这两种操作非常复杂,自己按照书上给的伪代码实现了一下,思路是基本理清了,这种太复杂的数据结构想完全记住是不太现实的,能够掌握要点,下次看的时候可以马上回忆起来就可以了。

头文件:

#ifndef _RED_BLACK_TREE_
#define _RED_BLACK_TREE_
#define RED 82
#define BLACK 66

typedef struct RBTreeNode
{
	unsigned int color;
	int key;
	struct RBTreeNode *left;
	struct RBTreeNode *right;
	struct RBTreeNode *pre;
}Node,*RBTree;
typedef struct RBRoot
{
	Node *root;
}RBRoot;

RBRoot *CreateTree();
void InsertTree(RBRoot *tree, int key);
void DeleteNode(RBRoot *tree, Node *z);
void PrintTree(RBRoot *tree);
#endif

函数声明文件:

#include<iostream>
#include<stdlib.h>
#include"rbtree.h"

static void LeftRotate(RBRoot *tree, Node *x);
static void RightRotate(RBRoot *tree, Node *y);
static void RBInsertFixUp(RBRoot *tree, Node *z);
static void PrintNode(Node *node,int key, int direction);
static void InsertNode(RBRoot *tree, Node *z);
static void RBTransplant(RBRoot *tree, Node *u, Node *v);
static void RBDeleteFixUp(RBRoot *tree, Node *x);

RBRoot *CreateTree()
{
	RBRoot *tree = (RBRoot *)malloc(sizeof(RBRoot));
	tree->root = NULL;
	return tree;
}
static void LeftRotate(RBRoot *tree, Node *x)
{
	Node *y = x->right;
	x->right = y->left;
	if (y->left != NULL)
		y->left->pre = x;
	y->pre = x->pre;
	if (x->pre == NULL)
		tree->root = y;
	else if (x == x->pre->left)
		x->pre->left = y;
	else
		x->pre->right = y;
	y->left = x;
	x->pre = y;
}
static void RightRotate(RBRoot *tree, Node *y)
{
	Node *x = y->left;
	y->left = x->right;
	if (x->right != NULL)
		x->right->pre = y;
	x->pre = y->pre;
	if (y->pre == NULL)
		tree->root = x;
	else if (y == y->pre->left)
		y->pre->left = x;
	else
		y->pre->right = x;
	y->pre = x;
	x->right = y;
}
static void RBInsertFixUp(RBRoot *tree, Node *z)
{
	while (z->pre!=NULL&&z->pre->pre!=NULL&&z->pre->color == RED)//自己和父亲都是红结点
	{
		if (z->pre == z->pre->pre->left)
		{
			Node *y = z->pre->pre->right;
			if (y!=NULL&&y->color == RED)//叔也为红结点就把父亲和叔叔都变成红色,爷爷变成黑色,这样达到一个z变成爷爷上移的作用,且黑高不变
			{
				z->pre->color = BLACK;
				y->color = BLACK;
				z->pre->pre->color = RED;
				z = z->pre->pre;
			}
			else if (z == z->pre->right)//叔为黑且自己为右子树就进行一次左旋转换为第三种情况(叔不存在也是黑)
			{
				z = z->pre;
				LeftRotate(tree, z);
			}
			else//将父亲和爷爷的颜色交换并对爷爷进行一次右旋,这样转换为第一种情况
			{
				z->pre->color = BLACK;
				z->pre->pre->color = RED;
				RightRotate(tree, z->pre->pre);
			}
		}
		else//父亲为右子树的情况只要把上面的情况中所以Right和Left互换就行
		{
			Node *y = z->pre->pre->left;
			if (y!=NULL&&y->color == RED)
			{
				z->pre->color = BLACK;
				y->color = BLACK;
				z->pre->pre->color = RED;
				z = z->pre->pre;
			}
			else if (z == z->pre->left)
			{
				z = z->pre;
				RightRotate(tree, z);
			}
			else
			{
				z->pre->color = BLACK;
				z->pre->pre->color = RED;
				LeftRotate(tree, z->pre->pre);
			}
		}
	}
	tree->root->color = BLACK;//将根结点设为黑色
}
static void InsertNode(RBRoot *tree, Node *z)
{
	Node *y = NULL;
	Node *x = tree->root;
	while (x != NULL)//寻找合适的位置
	{
		y = x;
		if (z->key < x->key)
			x = x->left;
		else
			x = x->right;
	}
	z->pre = y;
	if (y == NULL)
		tree->root = z;
	else if (z->key < y->key)
		y->left = z;
	else
		y->right = z;
	z->left = NULL;
	z->right = NULL;
	z->color = RED;
	RBInsertFixUp(tree, z);
}
static void PrintNode(Node *node,int key, int direction)
{
	if (node != NULL)
	{
		if(direction==0)
			printf("%2d(B) is root\n", node->key);
		else
			printf("%2d(%c) is %2d's %6s child\n", node->key, node->color, key, direction == 1 ? "right" : "left");
		PrintNode(node->left, node->key, -1);
		PrintNode(node->right, node->key, 1);
	}
}
void PrintTree(RBRoot *tree)
{
	if (tree!=NULL&&tree->root != NULL)
		PrintNode(tree->root, tree->root->key, 0);
}
void InsertTree(RBRoot *tree, int key)
{
	Node* temp=(Node*)malloc(sizeof(Node));
	temp->key = key;
	temp->left = NULL;
	temp->right = NULL;
	temp->color = BLACK;
	InsertNode(tree, temp);
}
void RBTransplant(RBRoot *tree, Node *u, Node *v)//用v来取代u
{
	if (u->pre == NULL)
		tree->root = v;
	else if (u == u->pre->left)
		u->pre->left = v;
	else
		u->pre->right = v;
	v->pre = u->pre;
}
void RBDeleteFixUp(RBRoot *tree, Node *x)
{
	while (x != tree->root&&x->color == BLACK)
	{
		if (x == x->pre->left)
		{
			Node *w = x->pre->right;//x为y的右子树,w为x的兄弟
			if (w->color == RED)//情况1:兄弟为红色,左旋一次转换为情况2
			{
				w->color == BLACK;
				x->pre->color = RED;
				LeftRotate(tree, x->pre);
				w = x->pre->right;
			}
			else
			{
				if (w->left->color == BLACK&&w->right->color == BLACK)//情况2:兄弟的两个孩子都是黑色,将兄弟削去一层黑色,将x上移,转换为情况1234
				{
					w->color = RED;
					x = x->pre;
				}
				else if (w->right->color == BLACK)//情况3:兄弟的左孩子红右孩子黑,右旋一次转换为情况4
				{
					w->left->color = BLACK;
					w->color = RED;
					RightRotate(tree, w);
					w = x->pre->right;
				}
				else//情况4:兄弟的孩子都是红色,此时坐旋使原x的路径增加一个黑色,这种情况出现说明完成红黑平衡
				{
					w->color = x->pre->color;
					x->pre->color = BLACK;
					w->right->color = BLACK;
					LeftRotate(tree, x->pre);
					x = tree->root;
				}
			}
		}
		else
		{
			Node *w = x->pre->left;
			if (w->color == RED)
			{
				w->color == BLACK;
				x->pre->color = RED;
				RightRotate(tree, x->pre);
				w = x->pre->left;
			}
			else
			{
				if (w->left->color == BLACK&&w->right->color == BLACK)//情况2:兄弟的两个孩子都是黑色,将兄弟削去一层黑色,将x上移,转换为情况1234
				{
					w->color = RED;
					x = x->pre;
				}
				else if (w->left->color == BLACK)//情况3:兄弟的左孩子红右孩子黑,右旋一次转换为情况4
				{
					w->right->color = BLACK;
					w->color = RED;
					LeftRotate(tree, w);
					w = x->pre->left;
				}
				else//情况4:兄弟的孩子都是红色,此时坐旋使原x的路径增加一个黑色,这种情况出现说明完成红黑平衡
				{
					w->color = x->pre->color;
					x->pre->color = BLACK;
					w->left->color = BLACK;
					RightRotate(tree, x->pre);
					x = tree->root;
				}
			}
		}
	}
	x->color = BLACK;
}
void DeleteNode(RBRoot *tree,Node *z)
{
	Node *y,*x;
	y = z;
	unsigned int origin_color = y->color;
	if (z->left == NULL)
	{
		x = z->right;
		RBTransplant(tree, z, z->right);
	}
	else if (z->right == NULL)
	{
		x = z->left;
		RBTransplant(tree, z, z->left);
	}
	else
	{
		Node *temp = z->right;
		while (temp->left!= NULL)
			temp = temp->left;
		y = temp;
		origin_color = y->color;
		x = y->right;
		if (y->pre == z)
			x->pre = y;
		else
		{
			RBTransplant(tree, y, y->right);
			y->right = z->right;
			y->right->pre = y;
		}
		RBTransplant(tree, z, y);
		y->left = z->left;
		y->left->pre = y;
		y->color = z->color;
	}
	if (origin_color == BLACK)
		RBDeleteFixUp(tree, x);
}

实现文件:

#include<stdio.h>
#include<stdlib.h>
#include"rbtree.h"

int main()
{
	int test[] = { 10, 40,30,60,90,70,20,50,80};
	RBRoot* tree = CreateTree();
	for (int i = 0; i < sizeof(test)/sizeof(int); i++)
		InsertTree(tree, test[i]);
	PrintTree(tree);
	DeleteNode(tree,tree->root);
	PrintTree(tree);
	return 0;
}




posted @ 2016-08-24 22:25  seasonal  阅读(121)  评论(0编辑  收藏  举报