IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 红黑树C语言代码实现(插入,删除) -> 正文阅读

[数据结构与算法]红黑树C语言代码实现(插入,删除)

#define _CRT_SECURE_NO_WARNINGS
/*vs studio不用这句话会给scanf报错*/
#include <stdio.h>
#include<stdlib.h>
#define RED 1
#define BLACK 0
typedef struct rbtree_node {
	int weight;
	int color;
	struct rbtree_node* left, * right, * parent;
}*tree;
typedef struct rbtree_root {
	tree root;
	tree nil;//叶节点
}*tree_root;
tree_root make_root();
void make_tree(tree_root root);
tree_root insert_tree(tree_root root, tree X);
void left_rotate(tree_root root, tree X);
void right_rotate(tree_root root, tree X);
tree find(tree_root root, tree temp, int X, int* flag);
void exchange_color(tree a, tree b);
void PreorderTraversal(tree_root root, tree BT);
void InorderTraversal(tree_root root, tree BT);
void delete_tree(tree_root, int X);
tree find_min(tree_root root, tree temp);
tree get_brother(tree temp);
void delete_x(tree temp);
tree delete_treeLeft(tree_root root, tree temp);
tree delete_treeRight(tree_root root, tree temp);
tree delete_treeplus(tree_root root, tree temp);
void destroy_tree(tree_root root, tree BT);
void destroy_root(tree_root root);
void display(tree_root root);
void delete_input(tree_root root);

int main() {
	tree_root root = make_root();
	make_tree(root);
	display(root);
	delete_input(root);
	display(root);
	destroy_tree(root, root->root);
	destroy_root(root);
	return 0;
}
void make_tree(tree_root root) {
	int treeAmount;
	int weight;
	printf("请输入结点数目:\n");
	scanf("%d", &treeAmount);
	for (int i = 0; i < treeAmount; i++) {
		scanf("%d", &weight);
		tree temp = (tree)malloc(sizeof(struct rbtree_node));//建结点
		temp->color = RED;//新结点默认红色
		temp->weight = weight;
		temp->parent = temp->left = temp->right = root->nil;
		root = insert_tree(root, temp);//插入结点
	}
	return;
}
tree_root insert_tree(tree_root root, tree X) {
	if (root->root == root->nil) {//空树
		root->root = X;
		root->root->color = BLACK;
		root->root->parent = root->nil;
	}
	else {
		int flag = 1;//查看元素是否已经存在
		if (X->parent == root->nil && X != root->root) {//判断X是否新插入的结点
			tree temp = find(root, root->root, X->weight, &flag);
			if (flag) {//元素不存在,插入
				if (X->weight < temp->weight)
					temp->left = X;
				else
					temp->right = X;
				X->parent = temp;
			}
			else {
				printf("插入元素%d已存在\n", X->weight);
				free(X);
				return root;
			}
		}
		if (X->parent->color == RED) {//插入后,出现两个连续红色
			if (X->parent->parent->left->color == X->parent->parent->right->color) {//父亲和伯伯颜色一样,两者都是红色
				X->parent->parent->left->color = X->parent->parent->right->color = BLACK;
				if (X->parent->parent != root->root) {//爷爷不是根结点
					X->parent->parent->color = RED;
					insert_tree(root, X->parent->parent);//爷爷作为新结点,检查是否和曾爷爷同为红色
				}
			}
			else if (X->parent->parent->left->color == RED) {//父亲和伯伯颜色不一样,且父亲在爷爷的左子树
				if (X->parent->right->color == RED) {
					X = X->parent;
					left_rotate(root, X);
				}
				exchange_color(X->parent, X->parent->parent);
				right_rotate(root, X->parent->parent);
			}
			else {//父亲和伯伯颜色不一样,父亲在爷爷的右子树
				if (X->parent->left->color == RED) {
					X = X->parent;
					right_rotate(root, X);
				}
				exchange_color(X->parent, X->parent->parent);
				left_rotate(root, X->parent->parent);
			}
		}
	}
	return root;
}
tree_root make_root() {//建立根结点及叶结点
	tree_root temp = (tree_root)malloc(sizeof(struct rbtree_root));
	temp->nil = (tree)malloc(sizeof(struct rbtree_node));
	temp->nil->color = BLACK;
	temp->nil->weight = 0;
	temp->nil->parent = temp->nil->left = temp->nil->right = NULL;
	temp->root = temp->nil;
	return temp;
}
tree find(tree_root root, tree temp, int X, int* flag) {
	if (temp->weight < X) {
		if (temp->right != root->nil) {
			return find(root, temp->right, X, flag);
		}
		else {
			return temp;//X不在树中,且temp应该作为X的父亲
		}

	}
	else if (temp->weight > X) {
		if (temp->left != root->nil) {
			return find(root, temp->left, X, flag);
		}
		else {
			return temp;
		}
	}
	else if (temp->weight == X) {
		*flag = 0;//在树中找到元素,flag变0
		return temp;
	}
}
void exchange_color(tree a, tree b) {
	int color = a->color;
	a->color = b->color;
	b->color = color;
	return;
}
void left_rotate(tree_root root, tree X) {//左旋
	X->right->parent = X->parent;
	if (X != root->root) {
		if (X->parent->left == X)
			X->parent->left = X->right;
		else
			X->parent->right = X->right;
	}
	X->parent = X->right;
	if (X->right->left != root->nil)
		X->right->left->parent = X;
	X->right = X->right->left;
	X->parent->left = X;
	if (X == root->root) {
		root->root = X->parent;
		root->root->color = BLACK;
	}
	return;
}
void right_rotate(tree_root root, tree X) {//右旋
	X->left->parent = X->parent;//X的左儿子向X父亲建立关系
	if (X->parent->left == X)//X父亲向X左儿子建立关系
		X->parent->left = X->left;
	else
		X->parent->right = X->left;
	X->parent = X->left;//X向左儿子建立关系
	X->left->right->parent = X;//X的左儿子的右儿子向X建立关系
	X->left = X->left->right;//X向X的左儿子的右儿子建立关系
	X->parent->right = X;//X现在的父亲向X建立关系
	if (X == root->root) {//更换根结点
		root->root = X->parent;
		//root->root->color = BLACK;
	}
	return;
}
void PreorderTraversal(tree_root root, tree BT)
{
	if (BT != root->nil) {
		printf("%d,", BT->weight, BT->color);
		if (BT->color == 1)
			printf("红\t");
		else
			printf("黑\t");
		PreorderTraversal(root, BT->left);
		PreorderTraversal(root, BT->right);
	}
}
void InorderTraversal(tree_root root, tree BT)
{
	if (BT != root->nil) {
		InorderTraversal(root, BT->left);
		printf("%d,", BT->weight);
		if (BT->color == 1)
			printf("红\t");
		else
			printf("黑\t");
		InorderTraversal(root, BT->right);
	}
}
void delete_tree(tree_root root, int X) {//这种情况下的X必然有一个空的子结点,情况简单
	int flag = 1;
	tree temp = find(root, root->root, X, &flag);
	tree mark = temp;
	if (flag) {
		printf("要删除的元素不存在\n");
		return;
	}
	if (temp->right == root->nil) {//X不存在右子树
		if (temp->color == BLACK && temp->left->color == RED) {//这种情况换值后直接删
			temp->weight = temp->left->weight;
			delete_x(temp->left);
			return;
		}
		if (temp->color == RED) {//直接删
			delete_x(temp);
			return;
		}
		if (temp == root->root) {//树只有X一个结点,删了树变空
			free(temp);
			root->root = root->nil;
			return;
		}
	}
	if (temp->right != root->nil) {//寻找X右子树的最小值,将最小值放入X结点,问题转变成删除X右子树最小值的结点
		temp = find_min(root, temp->right);
		mark->weight = temp->weight;
		temp->weight = X;
	}
	if (temp->color == RED) {//红色直接删
		delete_x(temp);
		return;
	}

	if (temp->right->color == RED) {//换值后直接删
		temp->weight = temp->right->weight;
		delete_x(temp->right);
		return;
	}
	tree to_delete = delete_treeplus(root, temp);//其他情况,此时X必为黑色
	delete_x(to_delete);
}
tree find_min(tree_root root, tree temp) {
	while (temp->left != root->nil)
		temp = temp->left;
	return temp;
}
tree get_brother(tree temp) {
	if (temp->parent->left != temp)
		return temp->parent->left;
	else
		return temp->parent->right;
}
void delete_x(tree temp) {
	if (temp == temp->parent->right) {
		temp->parent->right = temp->right;
		temp->right->parent = temp->parent;
	}
	else {
		temp->parent->left = temp->right;
		temp->right->parent = temp->parent;
	}
	free(temp);
	return;
}
tree delete_treeLeft(tree_root root, tree temp) {//删除结点在父亲的左子树上
	if (temp->color == RED) {//一次性直接删除成功的话不会触发这个,触发这个的时候,X(temp)的子树的黑权重必然比X的兄结点的子树少1
		temp->color = BLACK;
		return temp;
	}
	if (temp->parent->color == BLACK) {
		tree brother = get_brother(temp);
		if (brother == root->nil)
			return temp;//不是一次性删除可能会出现这种情况,直接返回就行
		if (brother->color == BLACK) {
			if (brother->right->color == RED) {//兄弟右儿子红色
				brother->right->color = BLACK;
				left_rotate(root, brother->parent);
				return temp;
			}
			if (brother->left->color == RED) {//兄弟左儿子红色
				brother->left->color = BLACK;
				right_rotate(root, brother);
				left_rotate(root, temp->parent);
				return temp;
			}
			if (brother->left->color == BLACK && brother->right->color == BLACK) {//最麻烦的情况
				if (temp->left->color == RED || temp->right->color == RED){ //一次性删除不会触发这个。同时减少父亲另一边的黑权重,使左右黑权重平衡
					brother->color = RED;
					if (temp->parent != root->root) {//三个黑色这种情况,如果没回溯到根结点,这样处理会导致根的左右黑权重不平衡。
						//解决方法一是回溯时触发其他颜色的情况,会直接解决平衡问题。二是回溯到根结点,还是三个黑,再这样处理根另一边黑权重-1,重新平衡。
						delete_treeplus(root, temp->parent);
					}
					return temp;
				}
			temp->color = RED;
			brother->color = RED;
			brother->parent->color = BLACK;
			if (brother->parent != root->root)//不是根结点这种处理会使根左右黑权重不平衡
				delete_treeplus(root, temp->parent);
			return temp;
			}
		}
		else {//父亲为黑,兄弟为红,此情况转化成父亲黑色,兄弟黑色再做处理
			exchange_color(brother, brother->parent);
			left_rotate(root, brother->parent);
		}
	}
	if (temp->parent->color == RED) {
		tree brother = get_brother(temp);
		/*if (brother == root->nil) {
			temp->parent->color = BLACK;
			printf("不会发生");
			return temp;
		}*/
		if (brother->right->color == RED) {//兄弟右儿子为红
			exchange_color(brother, brother->right);
			temp->parent->color = BLACK;
			left_rotate(root, brother->parent);
			return temp;
		}
		if (brother->left->color == BLACK && brother->right->color == BLACK) {//兄弟结点左右儿子为空或者黑色
			exchange_color(brother, brother->parent);
			return temp;
		}
		else {//兄弟结点左儿子为红色的情况
			temp->parent->color = BLACK;
			right_rotate(root, brother);
			left_rotate(root, temp->parent);
			return temp;
		}
	}
}
tree delete_treeRight(tree_root root, tree temp) {//删除结点在父亲的右子树上,处理基本为Left的镜像
	if (temp->color == RED) {
		temp->color = BLACK;
		return temp;
	}
	if (temp->parent->color == BLACK) {
		tree brother = get_brother(temp);
		if (brother == root->nil)
			return temp;
		if (brother->color == BLACK) {
			if (brother->left->color == RED) {
				brother->left->color = BLACK;
				right_rotate(root, temp->parent);
				return temp;
			}
			if (brother->right->color == RED) {
				brother->right->color = BLACK;
				left_rotate(root, brother);
				right_rotate(root, temp->parent);
				return temp;
			}
			if (brother->left->color == BLACK && brother->right->color == BLACK) {
				if (temp->left->color == RED || temp->right->color == RED) {
					brother->color = RED;
					if (temp->parent != root->root) {
						delete_treeplus(root, temp->parent);
					}
					return temp;
				}
				temp->color = RED;
				brother->color = RED;
				brother->parent->color = BLACK;
				if (brother->parent != root->root) {
					delete_treeplus(root, temp->parent);
				}
				return temp;
			}
		}
		else {
			exchange_color(brother, brother->parent);
			right_rotate(root, brother->parent);
		}
	}
	if (temp->parent->color == RED ) {
		tree brother = get_brother(temp);
		/*if (brother == root->nil) {
			temp->parent->color = BLACK;
			printf("不会发生");
			return temp;
		}*/
		if (brother->left->color == BLACK && brother->right->color == BLACK) {
			brother->parent->color = BLACK;
			brother->color = RED;
			return temp;
		}
		if (brother->left->color == RED) {
			exchange_color(brother, brother->left);
			temp->parent->color = BLACK;
			right_rotate(root, temp->parent);
			return temp;
		}
		else {
			temp->parent->color = BLACK;
			left_rotate(root, brother);
			right_rotate(root, temp->parent);
			return temp;
		}
	}
}
tree delete_treeplus(tree_root root, tree temp) {
	if (temp->parent->right == temp)
		return delete_treeRight(root, temp);
	else
		return delete_treeLeft(root, temp);
}
void destroy_tree(tree_root root, tree BT)
{
	if (BT != root->nil) {
		destroy_tree(root, BT->left);
		destroy_tree(root, BT->right);
		free(BT);
	}
}
void destroy_root(tree_root root) {
	free(root->nil);
	free(root);
}
void delete_input(tree_root root) {
	printf("\n请输入要删除的树的数量:\n");
	int number;
	scanf("%d", &number);
	for (int i = number; i > 0; i--) {
		scanf("%d", &number);
		delete_tree(root, number);
	}
}
void display(tree_root root) {
	PreorderTraversal(root, root->root);
	printf("\n");
	printf("------------------------------------------------------------------------------------------\n");
	InorderTraversal(root, root->root);
}

参考了这篇文章:https://blog.csdn.net/weewqrer/article/details/51866488?utm_source=app&app_version=4.15.0&code=app_1562916241&uLinkId=usr1mkqgl919blen

如果发现数据出问题,欢迎反馈

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-20 16:00:39  更:2021-09-20 16:01:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 10:56:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码