⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rbtree.cpp

📁 数据结构的红黑树算法
💻 CPP
字号:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum boolean{RED, BLACK};
typedef enum boolean boolean;
typedef char keytype;

struct TreeNode{
	keytype key;
	boolean color;
	TreeNode* lchild;
	TreeNode* rchild;
	TreeNode* parent;
};

typedef struct TreeNode* pTREE;
typedef struct TreeNode* pNODE;

void LeftRotate(pTREE &RBTree, pNODE x);             //左旋转
void RightRotate(pTREE &RBTree, pNODE x);            //右旋转
pTREE RBInsert(pTREE RBTree, keytype k);             //插入操作
pTREE RBInsertFixup(pTREE RBTree, pNODE z);          //插入操作的辅助函数
pTREE RBDelete(pTREE RBTree, keytype k);            //删除操作
pTREE RBDeleteFixup(pTREE RBTree, pNODE x);          //删除操作的辅助函数
pNODE Search(pTREE RBTree, keytype k);              //查找数值k对应的结点,返回指向该结点的指针
void PrintNode(pTREE RBTree);
void MidVisit(pTREE RBTee);                         //中序遍历

 
int main(void)
{
	int i;
	pTREE RBTREE = NULL;           //RBTREE指向红黑树的根结点
	char str[] = "ALGORITHM";
	int count = (int)strlen(str);

	for (i = 0; i < count; i++){            
		RBTREE = RBInsert(RBTREE, str[i]);
		printf("插入 %c 之后:\n", str[i]);
		MidVisit(RBTREE);
		putchar('\n');
	}

	
	for (i = 0; i < count; i++){
		if (i == (count - 1)){
			printf("删除 %c 之后:\n结点已完全删除,结束!\n", str[count-1]);
			exit(0);
		}
		RBDelete(RBTREE, str[i]);		
		printf("删除 %c 之后:\n", str[i]);
		MidVisit(RBTREE);
		putchar('\n');
	}

	system("pause");
	return 0;
}

//对结点x实施左旋
void LeftRotate(pTREE &RBTree, pNODE x)
{
	pNODE y = x->rchild;

	if (y == NULL)		
		return;
	
	x->rchild = y->lchild;          //把y的左子树变为x的右子树
	if (y->lchild != NULL)
		y->lchild->parent = x;
	y->parent = x->parent;          //x的父结点变为y的父结点

	if (x == RBTree)
		RBTree = y;
	else if (x == x->parent->lchild)
		x->parent->lchild = y;
	else
		x->parent->rchild = y;

	y->lchild = x;
	x->parent = y;
}

//对结点x实施右旋
void RightRotate(pTREE &RBTree, pNODE x)
{
	pNODE y = x->lchild;

	if (y == NULL)
		return;

	x->lchild = y->rchild;
	if (y->rchild != NULL)
		y->rchild->parent = x;
	y->parent = x->parent;

	if (x == RBTree)         //x是根结点
		RBTree = y;
	else if (x == x->parent->lchild)               //x是左儿子
		x->parent->lchild = y;
	else                                           //x是右儿子 
		x->parent->rchild = y;
	y->rchild = x;
	x->parent = y;
}

//像原来树中插入一个结点z,z的数据域为k,RBTree指向树的根结点
pTREE RBInsert(pTREE RBTree, keytype k)
{
	pNODE x = RBTree;
	pNODE y = NULL;
	pNODE z = (pNODE)malloc(sizeof(struct TreeNode));    //要插入的新结点
	z->key = k;

	while (x != NULL){             
		y = x;
		if (z->key < x->key){               //按查找树的规则进行插入
			if (x->lchild != NULL)
				x = x->lchild;
			else
				break;
		}
		else{
			if (x->rchild != NULL)
				x = x->rchild;
			else
				break;
		}
	}

	z->parent = y;
	if (y == NULL)
		RBTree = z;
	else{
		if (z->key < y->key)           //安排z是y的左儿子还是右儿子
			y->lchild = z;
		else
			y->rchild = z;
	}

	z->lchild = NULL;
	z->rchild = NULL;
	z->color = RED;
	return RBInsertFixup(RBTree, z);
}

//插入红色结点后可能违背红黑树的定义,下面函数对插入的结点z进行修正
pTREE RBInsertFixup(pTREE RBTree, pNODE z)
{
	pNODE zUncle;                 //z的伯父结点

 	while ((RBTree != z) && (z->parent->color == RED)){
		if (z->parent == z->parent->parent->lchild){ //如果z的父结点是z的祖父结点的左儿子
			zUncle = z->parent->parent->rchild;
			if ((zUncle != NULL) && (zUncle->color == RED)){              //伯父结点的颜色同样为RED
				z->parent->color = BLACK;               
				zUncle->color = BLACK;
				z->parent->parent->color = RED;
				z = z->parent->parent;               //进行循环
			}
			else{
				if (z == z->parent->rchild){            
					z = z->parent;
					LeftRotate(RBTree, z);
				}
				z->parent->color = BLACK;               
				z->parent->parent->color = RED;
				RightRotate(RBTree, z->parent->parent);
			}
		}

		else{
			zUncle = z->parent->parent->lchild;
			if ((zUncle != NULL) && (zUncle->color == RED)){
				z->parent->color = BLACK;
				zUncle->color = BLACK;
				z->parent->parent->color = RED;
				z = z->parent->parent;               //进行循环
			}
			else{
				if (z == z->parent->lchild){
					z = z->parent;
					RightRotate(RBTree, z);
				}
				z->parent->color = BLACK;
				z->parent->parent->color = RED;
				LeftRotate(RBTree, z->parent->parent);
			}
		}
	}
	RBTree->color = BLACK;
	return RBTree;
}

//在红黑树中删除数据域为k的结点
pTREE RBDelete(pTREE RBTree, keytype k)
{
	pNODE x, y;	
	pNODE z = Search(RBTree, k);

	if (z == NULL)
		return RBTree;
	if ((z->lchild == NULL) || (z->rchild == NULL))
		y = z;
	else{
		y = z->rchild;
		while (y->lchild != NULL)
			y = y->lchild;
	}		
	if (y->lchild != NULL)      //如果被删除的结点左儿子非空,则使用x记录
		x = y->lchild;
	else
		x = y->rchild;
	if (x != NULL)
		x->parent = y->parent;
	if (y->parent == NULL)
		RBTree = x;
	else if (y == y->parent->lchild)
		y->parent->lchild = x;
	else
		y->parent->rchild = x;

	if (y != z)         //key有两个孩子时,实际删除的是z的直接后继y结点,所以要将后继结点的信息复制到key结点中
		z->key = y->key;
	if ((y->color == BLACK) && (x != NULL))
		RBDeleteFixup(RBTree, x);
	free(y);
	return RBTree;
}


pTREE RBDeleteFixup(pTREE RBTree, pNODE x)    //RBTree point to root
{
	pNODE xBrother;

	while ((x != RBTree) && (x->color == BLACK)){//如果color(x)为red,只需要讲color(x)=black就行了
		if (x == x->parent->lchild){
			xBrother = x->parent->rchild;
			if (xBrother == NULL)
				continue;
			if (xBrother->color == RED){
				xBrother->color = BLACK;
				x->parent->color = RED;
				LeftRotate(RBTree, x->parent);//修改了树结构,这一步后xBrother为x的祖父节点并且xBrother右孩子的black nodes不变
				xBrother = x->parent->rchild;//修正x得兄弟结点,现在color(father)=black right(father)=black,并且father->left得
			}
			if ((xBrother->lchild != NULL) && (xBrother->lchild->color == BLACK) && (xBrother->rchild != NULL) && (xBrother->rchild->color == BLACK)){
				xBrother->color = RED;
				x = x->parent;
			}
			else{
				if ((xBrother != NULL) && (xBrother->rchild->color == BLACK)){
					xBrother->lchild->color = BLACK;
					xBrother->color = RED;
					RightRotate(RBTree, xBrother);
					xBrother = x->parent->rchild;
				}
				xBrother->color = x->parent->color;
				x->parent->color = BLACK;
				xBrother->rchild->color = BLACK;
				LeftRotate(RBTree, x->parent);
				x = RBTree;
			}
		}
		else{
			xBrother = x->parent->lchild;
			if (xBrother == NULL)
				continue;
			if (xBrother->color == RED){
				xBrother->color = BLACK;
				x->parent->color = RED;
				LeftRotate(RBTree, x->parent);//修改了树结构,这一步后xBrother为x的祖父节点并且xBrother右孩子的black nodes不变
				xBrother = x->parent->lchild;//修正x得兄弟结点,现在color(father)=black right(father)=black,并且father->left得
			}
			if ((xBrother->rchild != NULL) && (xBrother->rchild->color == BLACK) && (xBrother->lchild != NULL) && (xBrother->lchild->color == BLACK)){
				xBrother->color = RED;
				x = x->parent;
			}
			else{
				if ((xBrother->lchild != NULL) && (xBrother->lchild->color == BLACK)){
					xBrother->rchild->color = BLACK;
					xBrother->color = RED;
					LeftRotate(RBTree, xBrother);
					xBrother = x->parent->lchild;
				}
				xBrother->color = x->parent->color;
				x->parent->color = BLACK;
				xBrother->lchild->color = BLACK;
				RightRotate(RBTree, x->parent);
				x = RBTree;
			}
		}
	}
	x->color = BLACK;
	return RBTree;
}

//寻找值k对应的结点
pNODE Search(pTREE RBTree, keytype k)
{
	pNODE x = RBTree;

	do{
		if (k == x->key)
			break;
		if (k < x->key){
			if (x->lchild != NULL)
				x = x->lchild;
			else
				break;
		}
		else{
			if (x->rchild != NULL)
				x = x->rchild;
			else
				break;
		}
	} while (NULL != x);	

	return x;
}

void PrintNode(pNODE node)
{
	char* color[] = {"RED", "BLACK"};

	printf("Key = %c,\tcolor = %s", node->key, color[node->color]);
	if (node->parent != NULL)
		printf(",\tparent = %c", node->parent->key);
	if (node->lchild != NULL)
		printf(",\tleft = %c", node->lchild->key);
	if (node->rchild != NULL)
		printf(",\tright = %c", node->rchild->key);
	printf("\n");
}


void MidVisit(pTREE RBTree)
{
	if (RBTree != NULL){
		if (RBTree->lchild != NULL)
			MidVisit(RBTree->lchild);
		PrintNode(RBTree);
		if (RBTree->rchild != NULL)
			MidVisit(RBTree->rchild);
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -