红黑树判断PAT 1135 Is It A Red-Black Tree
题目链接:
https://pintia.cn/problem-sets/994805342720868352/problems/994805346063728640
思路:
红黑树需要满足的5个条件:
(1) Every node is either red or black.
(2) The root is black.
(3) Every leaf (NULL) is black.
(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.
需要根据程序来判断的分别是(2),(4),(5)。对于(2)而言,跟节点必须是黑色的,可以通过根节点的值和0的大小来判断;对于(4),如果节点是红色的,那么他的孩子节点一定是黑色的,也就是说不能连续两个红色的节点在树的分枝上;对于(5),从任意一个节点开始到叶子节点所经过的黑色节点相等,分别对左边的分值和右边的分值统计起到叶子节点所经过的黑色节点的数目,如果两边不相等,说明不是红黑树。
具体见代码,强烈推荐柳神的博客,写的太好了!
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;
struct node{
int v;
node *left,*right;
};
node *build(node *root,int x){
if(root==NULL){
root=new node();
root->v=x;
root->left=root->right=NULL;
return root;
}
if(abs(x)<=abs(root->v))//小于等于
root->left=build(root->left,x);
else
root->right=build(root->right,x);
return root;
}
int judge1(node *root){//不含两个连续的红色节点,条件4
if(root==NULL) return 1;
if(root->v<0){
if(root->left!=NULL&&root->left->v<0) return 0;
if(root->right!=NULL&&root->right->v<0) return 0;
}
return judge1(root->left)&&judge1(root->right);
}
int getnum(node *root){
if(root==NULL) return 0;
int l=getnum(root->left);
int r=getnum(root->right);
return root->v<0?max(l,r):max(l,r)+1;
}
int judge2(node *root){
if(root==NULL) return 1;//条件5
int l=getnum(root->left);
int r=getnum(root->right);
if(l!=r) return 0;
return judge2(root->left)&&judge2(root->right);
}
int main(int argc, char** argv) {
int k;
scanf("%d",&k);
while(k--){
int n;
scanf("%d",&n);
node *root=NULL;
for(int i=1;i<=n;i++){
int x;
scanf("%d",&x);
root=build(root,x);
}
if(root->v<0||judge1(root)==0||judge2(root)==0)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}