題意:給一個紅黑樹的先序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;
}