1135 Is It A Red-Black Tree

题目大意

给一棵二叉搜索树的前序遍历,判断它是否为红黑树,是输出Yes,否则输出No。

思路解析

第一眼看到红黑树着实吓了一跳,暗想陈姥姥真狠……但是题意倒不难,一遍就AC了。
本题比较纠结的是第3条注解,是在不理解什么意思,于是直接把它忽略了,事实证明没有任何影响。所以本题所用到的红黑树判定条件是这样的:
1. 根节点是黑的;
2. 红节点的孩子都是黑的;
3. 对于任意一个节点,从它遍历到它的所有叶子子孙所经历的黑节点个数是相等的。
前两点都好判断,第三点仔细想一想:树又不是图,树只有一个入度,只要保证根节点到所有叶子节点所经历的黑节点个数都相等不就满足了吗,所以一遍DFS就可以判断出来。

示例代码

#include<iostream>
#include<map>
#include<set>
using namespace std;
struct node{
public:
	int val;
	struct node* left, *right;	
};
map<int, int> mapp;//value为1说明是红树
node* build(node* tree, int val) {
	if (tree == NULL) {
		tree = new node();
		tree->val = val;
		return tree;
	}
	if (val < tree->val) tree->left = build(tree->left, val);
	if (val > tree->val) tree->right = build(tree->right, val);
	return tree;
}
bool isover;
bool judge1(node* tree, int pre) {//检测节点是红的,它的两个孩子都是黑的  pre为1表示当前节点的父节点是红的
	if (tree == NULL || !isover) return true;
	if (pre == 1) {
		if ((tree->left != NULL && mapp[tree->val] == 1)) {
			isover = false;
			return false;
		}
	}
	if(isover)
		judge1(tree->left, mapp[tree->val]);
	if(isover)
	    judge1(tree->right, mapp[tree->val]);
	return isover;
}
set<int> se;//存放所有从根到叶子节点的路径所经历的黑节点个数
void judge2(node* tree,int count) {
	if (tree == NULL) {//遍历到了叶子节点
		se.insert(count);
		return;
	}
	if (mapp[tree->val] == 0) {
		judge2(tree->left, count + 1);
		judge2(tree->right, count + 1);
	}
	else {
		judge2(tree->left, count);
		judge2(tree->right, count);
	}
}
int main() {
	int n, m, val;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%d", &m);
		mapp.clear();
		se.clear();
		node* tree = NULL;
		isover = true;
		for (int j = 0; j < m; j++) {
			scanf("%d", &val);
			val < 0 ? mapp[abs(val)] = 1 : mapp[val] = 0;
			tree = build(tree, abs(val));
		}
		bool flag = true;
		if (mapp[tree->val] == 1 || !judge1(tree, 0)) flag = false;
		if (flag) judge2(tree, 0);
		if (se.size() > 1 || !flag) 
			printf("No\n");
		else 
			printf("Yes\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值