PAT 1135 Is It A Red-Black Tree——糟糕的出题

这题真是修bug修到崩溃!

题目

废话

这题最大问题在于图和描述不符
而且描述为英文,加重了题意的模糊
看了网上的一些解法,大都会觉得这题出的很奇怪
表述非常不明确

理解题意

1.题目中的图是这样
在这里插入图片描述
而真正意义上的红黑树是这样的
在这里插入图片描述
发现区别了嘛?
原因就在于要挂这些黑色的叶节点
2.可能你还是觉得奇怪?
参考这位同学的测试点推测
其中提到

1
3
1 2 -3
No

你可以想想为什么这种树是no
3.题目中有2句话,也暗示了图的不对劲
在这里插入图片描述
在这里插入图片描述

具体写法

  1. 常规按照前序和BST生成树

  2. 再按照上述理解,插入黑色叶节点
    必须用后序遍历插入

  3. 然后判断

    对于红结点孩子全黑,我这里用了额外的容器保存结点,这样便于直接扫描全部红结点
    对于判断黑结点数量,必须用先序遍历
    4.另外我这里对树进行删除,从而节约空间

代码
#include<bits/stdc++.h>
using  namespace std;

#define black 0
#define red 1
typedef struct node {
	int color;
	int key;
	struct node* lchild, * rchild;
	node(int x,int y) {
		key = abs(x);
		color = y;
		lchild = rchild = NULL;
	}
}RBTree;
int situation{ 0 };
int quantity{ 0 };
vector<RBTree*>static_node;
vector <int>hight;

RBTree* insert(int x, RBTree* root);
RBTree* insertNULL(RBTree* T);
void ClearTree(RBTree* root);
bool PrintJudge(RBTree* root);
void walk(int high, RBTree* T);
int main() {
	scanf("%d", &situation);
	RBTree* root = NULL;
	for (int i = 0; i < situation; i++) {
		scanf("%d", &quantity);
		int x;
		for (int j = 0; j < quantity; j++) {
			scanf("%d", &x);
			root = insert(x, root);
		}
		root = insertNULL(root);
		PrintJudge(root) ? printf("Yes\n") : printf("No\n");
		ClearTree(root);
		root = NULL;//因为删掉内存,root会被扔到奇怪的地方,因此需重新赋值NULL
		hight.clear();
		static_node.clear();
	}
	return 0;
}

RBTree* insert(int x, RBTree* root) {
	if (root == NULL) {
		int y;
		x > 0 ? y = black : y = red;
		root = new RBTree(x, y);
		static_node.push_back(root);
	}
	else {
		abs(x) > root->key ? root->rchild = insert(x, root->rchild) : root->lchild = insert(x, root->lchild);
	}
	return root;
}
RBTree* insertNULL(RBTree* T) {//注意不能在插入时进行同步插入NULL结点,原因是后序可能有点正好放入这个空结点
	if (T->lchild != NULL) 
		insertNULL(T->lchild);
	if (T->rchild != NULL) 
		insertNULL(T->rchild);
	if (T->lchild == NULL) {
		RBTree* q = new node(0, black);
		T->lchild = q;
	}
	if (T->rchild == NULL) {
		RBTree* p = new node(0, black);
		T->rchild = p;
	}
	return T;
}
void ClearTree(RBTree* root) {
	if (root != NULL) {
		ClearTree(root->lchild);
		ClearTree(root->rchild);
		delete(root);
	}
}
bool PrintJudge(RBTree* root) {
	if (root->color == red) 
		return false;
	for (auto i : static_node) {
		if (i->color == red && i->lchild != NULL && i->rchild != NULL) {
			if (i->lchild->color != black || i->rchild->color != black) 
				return false;
		}
	}
	int count{ 0 };
	walk(count, root);
	for (auto i = hight.begin(); i != hight.end(); i++) {
		if (hight[0] != *i) 
			return false;
	}
	return true;
}
void walk(int high, RBTree* T) {//遍历高度
	if (T->color == black) 
		(high)++;
	if (T->lchild == NULL && T->rchild == NULL) {
		hight.push_back(high);
		return;
	}
	if (T->lchild != NULL) 
		walk(high, T->lchild);
	if (T->rchild != NULL) 
		walk(high, T->rchild);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值