0
点赞
收藏
分享

微信扫一扫

PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】


目录

​​1,题目描述​​

​​题目大意​​

​​ 知识补充​​

​​2,思路​​

​​数据结构​​

​​算法​​

​​3,AC代码​​

​​4,解题过程​​

1,题目描述

PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】_1135

PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】_红黑树的性质 二叉树构建_02

Sample Input:

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

 

Sample Output:

Yes
No
No

题目大意

判断一棵树是否为红黑树。为了简便,题目中正数为黑色节点,负数代表红色节点,值的相对大小通过绝对值比较。

红黑树满足的性质:

  • (1) Every node is either red or black.:节点非黑即红;
  • (2) The root is black.:根节点为黑色(根节点大于0);
  • (3) Every leaf (NULL) is black.:规定空节点(NULL)为黑色;
  • (4) If a node is red, then both its children are black.:当一个节点为红色时,其所有孩子节点为黑色;
  • (5) For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.:对每个结点,从该节点向下延申到每个叶子节点的路径中,所有路径含有的黑色节点数目相同;

 知识补充

这篇文章讲解的很详细​​@hucongWh【红黑树】​​;

这篇文章介绍实例,动态构建红黑树,挺有意思​​@日拱一兵【红黑树,超强动静图详解,简单易懂】​​

 

2,思路

(解决这道题不需要对红黑树有很深刻的认识,只需要判断是否符合性质即可)

用到先序加中序遍历构建二叉树,具体操作可以参考这里​​@&再见萤火虫&【PAT_甲级_1020 Tree Traversals (25分) (C++)【树的遍历】】​​

数据结构

  • struct node{
    int key;
    node *left = NULL, *right = NULL;
    };动态二叉链表存储节点;
  • int pre[35], in[35]:先序遍历序列,中序遍历序列(即数组从小到大排序);
  • unordered_set<int> record:记录节点到所有叶节点路径中,黑色节点的数目,若record.size()==1则该节点符合条件5,否则说明黑色节点数目不唯一;

算法

  1. 获得二叉树的先序和中序(由于是balanced binary search tree,所以中序遍历即从小到大的排序)遍历;
  2. PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】_1135_03

  3. 根据先序和中序遍历,构建二叉树:
  4. PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】_甲级_04

  5. 设计函数getBlackNum,并利用unordered_set<int> record记录节点到所有叶节点路径中,黑色节点的数目,若record.size()==1则该节点符合条件5,否则说明黑色节点数目不唯一;
  6. PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】_甲级_05

  7. 利用DFS遍历二叉树。对每个节点调用函数getBlackNum判断是否满足性质5;当节点为红色时判断其子节点是否满足性质4。利用全局变量flag记录目前为止是否符合红黑树性质,是则继续,不是则返回;
  8. PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】_甲级_06

 

3,AC代码

#include<bits/stdc++.h>
using namespace std;
struct node{
int key;
node *left = NULL, *right = NULL;
};
int pre[35], in[35], K, N, key; //K判断次数 N节点数
bool flag;
unordered_set<int> record; //记录节点到所有叶节点路径中 黑色节点的数目 若record.size()==1则该节点符合条件5

bool cmp1(int a, int b){ return abs(a) < abs(b);}
void buildTree(node *&r, int root, int left, int right){// !!!*&
if(left > right) return;
if(r == NULL){
r = new node();
r->key = pre[root];
}
int i = left;
while(i <= right && in[i] != pre[root])
i++;
buildTree(r->left, root+1, left, i-1);
buildTree(r->right, root+(i-left)+1, i+1, right);
}
void getBlackNum(node *n, int num){
if(n == NULL || n->key > 0) //黑色节点
num++;
if(n == NULL){
record.insert(num);
return;
}
getBlackNum(n->left, num);
getBlackNum(n->right, num);
}
void dfsJudge(node *tree){
if(tree != NULL && flag == true){
record.clear();
getBlackNum(tree, 0);
if(record.size() > 1) flag = false; //判断该节点对应的条件5
if(flag == true && tree->key < 0){ //判断红色节点是否满足条件4
if(tree->left != NULL && tree->left->key < 0)
flag = false;
if(tree->right != NULL && tree->right->key < 0)
flag = false;
}
if(flag == true)
dfsJudge(tree->left);
if(flag == true)
dfsJudge(tree->right);
}
else return;
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif // ONLINE_JUDGE
cin>>K;
for(int i = 0; i < K; i++){
flag = true;
scanf("%d", &N);
for(int j = 0; j < N; j++){
scanf("%d", &pre[j]);
if(pre[j] == 0) flag = false;
}
if(pre[0] <= 0)
flag = false;
else{
memcpy(in, pre, N*sizeof(int)); //pre数组拷贝到in数组中
sort(in, in + N, cmp1); // !!!不是sort(pre, pre + N, cmp1);
node *root = NULL;
buildTree(root, 0, 0, N-1);
dfsJudge(root);
}
printf("%s\n", flag ? "Yes":"No");
}
return 0;
}

 

4,解题过程

一发入魂o(* ̄▽ ̄*)ブ

PAT_甲级_1135 Is It A Red-Black Tree (30point(s)) (C++)【红黑树/先序+中序构建二叉树/判断红黑树性质】_PAT_07

 

举报

相关推荐

0 条评论