C/C++ 红黑树

红黑树在二叉搜索树的基础上建立,每个点新增颜色与父亲,以颜色关系达到左右子树的相对平衡

结构

相比二叉树,多了父指针以及颜色的变量。

typedef struct node {
	int nValue;
	struct node* left;
	struct node* right;
	struct node* father;
	int color;
}*binarytree, Binarytree;

红黑树的性质:

  1. 每个结点不是红色的就是黑色的。
  2. 根是黑色的。
  3. 终端结点会被认为是黑色的。
  4. 不允许有两个红色结点为父子关系。
  5. 从任意结点向下出发,所经历的黑结点数目相同。
  6. 不会有某一条路径的长度大于其他路径的二倍。

红黑树的前置知识:左右旋

按照BST树(二叉搜索树)的规则对某一结点进行改造,以调节平衡。

左旋用于处理由右的右引起的不平衡。

右旋用于处理由左的左引起的不平衡。

右旋图示:

 左旋同理。

左旋代码:

void left_rotate(binarytree now) {
	binarytree x = now->father;
	binarytree a = now;
	binarytree b = a->right;
	binarytree e = b == nullptr ? nullptr : b->left;
	if (x != nullptr) {
		if (x->right == a) x->right = b;
		if (x->left == a) x->left = b;
	}
	if(b) b->father = x;
	a->right = e;
	if(b) b->left = a;
	if (e != nullptr) e->father = a;
	a->father = b;
}

右旋代码:

void right_rotate(binarytree now) {
	binarytree x = now->father;
	binarytree a = now;
	binarytree b = a->left;
	binarytree e = b == nullptr ? nullptr : b->right;
	if (x != nullptr) {
		if (x->left == a) x->left = b;
		if (x->right == a) x->right = b;
	}
	if(b) b->father = x;
	a->left = e;
	if (b) b->right = a;
	if (e != nullptr) e->father = a;
	a->father = b;
}

红黑树的添加结点

当一个新结点被添加时,我们先认为他是红色的。再进行旋转、变色操作。

注意,添加位置按照BST(二叉搜索树)的规则进行添加。

规则如下:令新节点为Z

  1. 当根节点为空时,Z成为根节点。
  2. 如果他的父亲是黑色的,结束 。
  3. 如果他的父亲是红色的,且他的叔叔也是红色的,那么,父亲、叔叔变黑,爷爷变红,将爷爷作为新的Z,重新讨论。
  4. 如果他的父亲为红且叔叔为黑,父亲是爷爷的左孩子,且Z是父亲的右孩子,以父亲为旋转点左旋,父亲成为新的Z,并继续判断其是否符合情况5。
  5. 如果他的父亲为红且叔叔为黑,父亲是爷爷的左孩子,且Z是父亲的左孩子,爷爷变红,以爷爷为旋转点右旋。
  6. 如果他的父亲为红且叔叔为黑,父亲是爷爷的右孩子,且Z是父亲的左孩子,以父亲为旋转点右旋,父亲成为新的Z,并继续判断其是否符合情况7。
  7. 如果他的父亲为红且叔叔为黑,父亲是爷爷的右孩子,且Z是父亲的右孩子,爷爷变红,以爷爷为旋转点左旋。

依照如上规则,进行创建。 

如上规则对照图示:

代码: 

红黑树的添加结点 / 创建一颗红黑树

binarytree create_rbt(int a[], int len) {
	binarytree root = (binarytree)malloc(sizeof(Binarytree));
	root->nValue = a[0];
	root->left = nullptr;
	root->right = nullptr;
	root->color = Black;
	root->father = nullptr;
	binarytree now;
	bool f = false;
	for (int i = 1; i < len; i++) {
		now = root;
		f = false;
		while (!f) {
			if (a[i] > now->nValue) {
				if (now->right == nullptr) {
					now->right = (binarytree)malloc(sizeof(Binarytree));
					now->right->nValue = a[i];
					now->right->left = nullptr;
					now->right->right = nullptr;
					now->right->father = now;
					now = now->right;
					f = true;
				}
				else now = now->right;
			}
			else {
				if (now->left == nullptr) {
					now->left = (binarytree)malloc(sizeof(Binarytree));
					now->left->nValue = a[i];
					now->left->left = nullptr;
					now->left->right = nullptr;
					now->left->father = now;
					now = now->left;
					f = true;
				}
				else now = now->left;
			}
		}
		now->color = Red;
		while (now != nullptr) {
			if (now->father == nullptr) { // 1
				printf("1: \n");
				now->color = Black;
				now = nullptr;
				continue;
			}
			if (now->father->color == Black) {// 2
				printf("2: \n");
				now->color = Red;
				now = nullptr;
				continue;
			}
			trav_front(root);
			printf("\n");
			binarytree tf = now->father;
			binarytree ta = (tf == tf->father->left) ? tf->father->right : tf->father->left;
			binarytree tg = now->father->father;
			printf("now = %d f = %d a = %d g = %d\n", now ? now->nValue : -1, tf ? tf->nValue : -1, ta ? ta->nValue : -1, tg ? tg->nValue : -1);
			if(ta) printf("%d-----%d\n", ta->nValue, ta->color);
			if (ta != nullptr && ta->color == Red) { // 3
				printf("3: \n");
				tf->color = Black;
				ta->color = Black;
				tg->color = Red;
				now = tg;
				continue;
			}
			if (tf != nullptr && tf == tg->left && now == tf->right) { // 4
				printf("4: \n");
				now = tf;
				left_rotate(now);
				continue;
			}
			if (tf != nullptr && tf == tg->left && now == tf->left) { // 5
				printf("5: \n");
				tf->color = Black;
				tg->color = Red;
				if (tg->father == nullptr) {
					root = tf;
				}
				right_rotate(tg);
				now = nullptr;
				continue;
			}
			if (tf != nullptr && tf == tg->right && now == tf->left) { // 6
				printf("6: \n");
				printf("now = %d f = %d a = %d g = %d\n", now ? now->nValue : -1, tf ? tf->nValue : -1, ta ? ta->nValue : -1, tg ? tg->nValue : -1);
				now = tf;
				left_rotate(now);
				continue;
			}
			if (tf != nullptr && tf == tg->right && now == tf->right) { // 7
				printf("7: \n");
				tf->color = Black;
				tg->color = Red;
				if (tg->father == nullptr) {
					root = tf;
				}
				right_rotate(tg);
				now = nullptr;
				continue;
			}
		}
	}
	root->father = nullptr;
	get_bstfa(root);
	return root;
}

红黑树的删除结点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值