题意:给一个红黑树的先序BST序列,判断是不是红黑树。
思路:本题没有红黑树的相当理解也OK,因为题目都给你描述清楚了。也没有任何AVL树旋转操作等。直接BST建树、遍历判断即可,应该算一个看名字很难其实考的是模拟的简单细节题。
坑点:1、这是多例输入,所以还要注意回收空间;其中一个小知识是,delete指针以后,系统只是回收了它的空间,但并不会改变指针的值。所以要根节点手动重新赋值为 NULL
2、红黑树中说叶子节点是黑色。这个“叶节点”指的是NULL节点。。。和平时写代码的时候的末尾节点概念不一样。。。所以本题中不用管它,不要没仔细看搞成 root->left==NULL&&root->right==NULL 的节点呀!
3、是个人问题。我的正负号用来判断结点颜色是在建树中的new环节,所以就灭去动它就建树了;而插入过程中选择是左子树还是右子树要去掉正负号来判断!结果未舍去正负号在左右子树选择的时候产生错误,还找了半天。。。所以编码思维和习惯要缜密一些,不然会有很多意想不到的问题。
Code:
代码里多了两个DEBUG用的函数,就懒得删了。
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define inf 100009
#define INF 0x3f3f3f3f
#define loop(x,y,z) for(x=y;x<z;x++)
int n,flag;
struct Node
{
int v;
Node *l,*r;
bool color;//1红0黑
Node(int v)
{
l=r=NULL;
color=v<0;
this->v=color?-v:v;
}
}*root;
void deleteTree(Node *root)
{
if(!root)return;
deleteTree(root->l);
deleteTree(root->r);
delete root;
}
void print(Node *root)//DEBUG
{
if(!root)return;
printf("father: %d ,sons : %d %d \n",root->v,root->l?root->l->v:-1,root->r?root->r->v:-1);
print(root->l);
print(root->r);
}
Node* insert(Node *root,int v)
{
if(!root)root=new Node(v);
else
{
if(abs(v)<root->v)root->l=insert(root->l,v);
else root->r=insert(root->r,v);
}
return root;
}
int checkColor(Node *root,Node *father)
{
if(!root)return 0;//NULL节点结束,无黑色
if(!flag)return -1;//结束剪枝,传递什么无所谓
if(!father&&root->color)flag=0;//根节点黑色
if(father&&father->color&&root->color)flag=0;//父红则子黑
int l=checkColor(root->l,root);
int r=checkColor(root->r,root);
if(l!=r)flag=0;
if(!root->color)l=l+1;//黑色统计
return l;
}
int main()
{
int i,j;
int T;
cin>>T;
while(T--)
{
deleteTree(root);
root=NULL;//重新声明
cin>>n;
loop(i,0,n)
{
cin>>j;
root=insert(root,j);
//print(root);printf("\n\n");
}
flag=1;
checkColor(root,NULL);
if(flag)printf("Yes\n");
else printf("No\n");
}
return 0;
}