1135. Is It A Red-Black Tree (30)
There is a kind of balanced binary search tree named red-black tree in the data structure. It has the following 5 properties:
(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.
For example, the tree in Figure 1 is a red-black tree, while the ones in Figure 2 and 3 are not.
![]() | ![]() | ![]() |
For each given binary search tree, you are supposed to tell if it is a legal red-black tree.
Input Specification:
Each input file contains several test cases. The first line gives a positive integer K (<=30) which is the total number of cases. For each case, the first line gives a positive integer N (<=30), the total number of nodes in the binary tree. The second line gives the preorder traversal sequence of the tree. While all the keys in a tree are positive integers, we use negative signs to represent red nodes. All the numbers in a line are separated by a space. The sample input cases correspond to the trees shown in Figure 1, 2 and 3.
Output Specification:
For each test case, print in a line "Yes" if the given tree is a red-black tree, or "No" if not.
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 17Sample Output:
Yes No No
红黑树条件:
1.结点要么黑要么红
2.根节点为黑
3.每个空节点为黑(这个理解了半天,看图一叶子结点有红也有黑啊,它这里意思应该是叶子结点在下去的空节点算作黑,这样就满足条件4,叶子红结点也有2个黑结点孩子)
4.红结点孩子为黑
5.每一个结点到其叶子结点的黑结点数相同。
写函数只要判断条件2 4 5
方法一:
根据前序,中序建树,为什么测试点1段错误呢?
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef struct Node *node;
int flag,flag2;
struct Node{
int x;
int fu;//0:+ 1:-
node left;
node right;
}pre[35],in[35];
bool cmp(Node a,Node b){
return a.x<b.x;
}
node build(int s1,int e1,int s2,int e2){//根据前序 中序建树
node T=(node)malloc(sizeof(struct Node));
T->fu=pre[s1].fu;
T->x=pre[s1].x;
T->left=T->right=0;
int root,i;
for(i=s2;i<=e2;i++){
if(in[i].x==pre[s1].x){
root=i;break;
}
}
if(root!=s2){
T->left=build(s1+1,s1+root-s2,s2,root-1);
}
if(root!=e2){
T->right=build(s1+root-s2+1,e1,root+1,e2);
}
return T;
}
void dfs(node T){
if(T){
if(T->fu){
if(T->left&&T->left->fu){//红结点有左孩子并且也为红
flag=1;return;
}
if(T->right&&T->right->fu){//红结点有右孩子并且也为红
flag=1;return;
}
}
dfs(T->left);
dfs(T->right);
}
}
int getblack(node T){
if(T){
int left=getblack(T->left);
int right=getblack(T->right);
if(left!=right){//左右黑结点数不相等
flag2=1;
}
int maxn=max(left,right);
if(T->fu==0){//若该节点为黑
maxn++;
}
return maxn;
}
else{
return 0;
}
}
int judge(node T){
if(T->fu){//条件2
return 0;
}
dfs(T);//条件4
if(flag){
return 0;
}
getblack(T);//条件5
if(flag2){
return 0;
}
return 1;
}
int main(){
int k,n,i,tmp;
scanf("%d",&k);
while(k--){
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&tmp);
pre[i].x=abs(tmp);
if(tmp<0){
pre[i].fu=1;
}
else{
pre[i].fu=0;
}
in[i]=pre[i];
}
sort(in,in+n,cmp);//二叉搜索树中序必升序
node T=0;
T=build(0,n-1,0,n-1);//根据前序 中序建树
flag=flag2=0;
if(judge(T)){
printf("Yes\n");
}
else{
printf("No\n");
}
}
}
方法二:
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
typedef struct Node *node;
int flag,flag2;
struct Node{
int x;
int fu;//0+ 1-
node left;
node right;
}pre[35],in[35];
void dfs(node T){
if(T){
if(T->fu){//红结点
if(T->left&&T->left->fu){//红结点有左孩子并且也为红
flag=1;return;
}
if(T->right&&T->right->fu){//红结点有右孩子并且也为红
flag=1;return;
}
}
dfs(T->left);
dfs(T->right);
}
}
int getblack(node T){
if(T){
int left=getblack(T->left);
int right=getblack(T->right);
if(left!=right){//左右黑结点数不相等
flag2=1;
}
int maxn=max(left,right);
if(T->fu==0){//若该节点为黑
maxn++;
}
return maxn;
}
else{
return 0;
}
}
int judge(node T){
if(T->fu){//条件2
return 0;
}
dfs(T);//条件4
if(flag){
return 0;
}
getblack(T);//条件5
if(flag2){
return 0;
}
return 1;
}
node insert(node T,Node a){//根据前序又是二叉搜索树 建树
if(!T){
T=(node)malloc(sizeof(struct Node));
T->fu=a.fu;
T->x=a.x;
T->left=T->right=0;
}
else if(a.x<T->x){
T->left=insert(T->left,a);
}
else{
T->right=insert(T->right,a);
}
return T;
}
int main(){
int k,n,i,tmp;
scanf("%d",&k);
while(k--){
scanf("%d",&n);
node T=0;
for(i=0;i<n;i++){
scanf("%d",&tmp);
pre[i].x=abs(tmp);
if(tmp<0){
pre[i].fu=1;
}
else{
pre[i].fu=0;
}
T=insert(T,pre[i]);//根据前序又是二叉搜索树 建树
}
flag=flag2=0;
if(judge(T)){
printf("Yes\n");
}
else{
printf("No\n");
}
}
}