我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805346063728640
题目描述:
题目翻译:
1135 这是一棵红黑树吗
在数据结构中有一种称为红黑树的平衡二叉搜索树。 它有以下5个属性:
(1)每个节点都是红色或黑色。
(2)根是黑色的。
(3)每个叶子(NULL)都是黑色的。
(4)如果一个节点是红色的,那么它的两个孩子都是黑色的。
(5)对于每个节点,从节点到后代叶子的所有简单路径包含相同数量的黑色节点。
例如,图1中的树是红黑树,而图2和3中的树则不是。
对于每个给定的二叉搜索树,你需要指出它是否是合法的红黑树。
输入格式:
每个输入文件包含几个测试用例。第一行给出正整数K(<= 30),即测试用例总数。对于每种情况,第一行给出正整数N(<= 30),即二叉树中的节点总数。第二行给出树的前序遍历序列。虽然树中的所有键都是正整数,但我们使用负号来表示红色节点。一行中的所有数字都用空格分隔。样例输入对应于图1,2和3中所示的树。
输出格式:
对每个测试用例,如果该树是一棵红黑树,则打印“Yes”,否则打印“No”。
输入样例:
3
9
7 -2 1 5 -4 -11 8 14 -15
9
11 -2 1 -7 5 -4 8 14 -15
8
10 -7 5 -6 8 15 -11 17
输出样例:
Yes
No
No
知识点:根据前序遍历重建二分搜索树、树的深度优先遍历
思路:先根据前序遍历重建二分搜索树,再深度优先遍历判断其是否是一棵红黑树
重建二分搜索树时,我们比较的应该是其绝对值,因为负号仅代表该节点是红色,不代表节点大小。来看红黑树的5个条件:
(1)条件1,题目自动满足。
(2)条件2,直接判断所建树的根结点是否是正数即可。
(3)条件3,无需判断。
(4)条件4,dfs过程中一旦出现了红节点(即负数节点),如果其有左孩子或右孩子,判断其是否是黑色即可。
(5)条件5,dfs记录到叶子节点的每条路径,递归终止时,判断路径上负数节点的个数,将个数存入set集合countBlack中,利用set集合的去重特性来判断树中每个节点到叶子所经过的黑色节点数是否相等。如果最后countBlack中只有一个元素,说明每个节点到叶子所经过的黑色节点数均相等,满足该条件,否则不满足该条件。
C++代码:
#include<iostream>
#include<vector>
#include<set>
#include<cmath>
using namespace std;
struct node {
int data;
node* lchild;
node* rchild;
};
set<int> countBlack;
vector<int> tempPath;
node* create(vector<int> levelOrder);
void dfs(node* nowVisit, bool &flag);
bool isRBTree(node* head);
int main() {
int K;
scanf("%d", &K);
for(int i = 0; i < K; i++) {
int N;
scanf("%d", &N);
vector<int> levelOrder;
int num;
for(int j = 0; j < N; j++) {
scanf("%d", &num);
levelOrder.push_back(num);
}
node* head = create(levelOrder);
if(isRBTree(head)) {
printf("Yes\n");
} else {
printf("No\n");
}
}
return 0;
}
node* create(vector<int> levelOrder) {
if(levelOrder.size() <= 0) {
return NULL;
}
node* head = new node();
head->data = levelOrder[0];
vector<int> left;
vector<int> right;
for(int i = 1; i < levelOrder.size(); i++) {
if(abs(levelOrder[i]) < abs(levelOrder[0])) {
left.push_back(levelOrder[i]);
} else {
right.push_back(levelOrder[i]);
}
}
head->lchild = create(left);
head->rchild = create(right);
return head;
}
void dfs(node* nowVisit, bool &flag) {
if(nowVisit == NULL) {
int count = 0;
for(int i = 0; i < tempPath.size(); i++) {
if(tempPath[i] > 0) {
count++;
}
}
countBlack.insert(count);
return;
}
if(nowVisit->data < 0) {
if(nowVisit->lchild != NULL) {
if(nowVisit->lchild->data < 0) {
flag = false;
}
}
if(nowVisit->rchild != NULL) {
if(nowVisit->rchild->data < 0) {
flag = false;
}
}
}
tempPath.push_back(nowVisit->data);
dfs(nowVisit->lchild, flag);
dfs(nowVisit->rchild, flag);
tempPath.pop_back();
}
bool isRBTree(node* head) {
if(head->data < 0) {
return false;
}
bool flag = true;
countBlack.clear();
tempPath.clear();
dfs(head, flag);
if(countBlack.size() != 1 || !flag) {
return false;
}
return true;
}
C++解题报告: