1. 程式人生 > >1135 Is It A Red-Black Tree

1135 Is It A Red-Black Tree

函數 one sequence int fine desc lin can child

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 17

Sample Output:

Yes No No 題意: 給出k個二叉搜索樹的前序序列,判斷該樹是否為紅黑樹。 思路: 紅黑樹的定義:
  • 結點的顏色非紅即黑
  • 根結點的顏色必須是黑色的
  • 如果某個結點為紅色,則它的孩子節點必須是黑色的。
    • 表明從每個葉子到根的所有路徑上不能有兩個連續的紅色節點。
  • 從任一節點到其每個葉子的所有簡單路徑都包含相同數目的黑色節點。
    • 所有最長的路徑都有相同數目的黑色節點,這就表明了沒有路徑能多於任何其他路徑的兩倍長。
紅黑樹的判斷:
  1. 根結點是否為黑色。
  2. 每條路徑的黑色節點相等。統計出一條路徑的黑色節點的個數,然後與其他路徑黑色節點個數進行比較。
  3. 不存在連續的紅色節點,判斷紅色節點的孩子節點是否為紅色。
代碼:
#include <cstdio>
#include <algorithm>
using namespace std;
#define BLACK 1
#define RED 0

struct Node{
    int val;
    int color;
    Node *lchild,*rchild;
    Node(int v){
        val=v>0?v:-v;
        color=v>0?BLACK:RED;
        lchild=rchild=nullptr;
    }
};

void insert(Node* &root,int val)
{
    if(root==nullptr){
        root=new Node(val);
        return;
    }
    if(abs(val)<root->val) insert(root->lchild,val);
    else insert(root->rchild,val);
}

//深度遍歷,計算黑色結點的個數以及判斷是否會出現連續兩個紅色結點
int totalBlackCnt=0;
bool flag=true;
void dfs(Node* root,int cnt)
{
    if(root==nullptr){
        if(cnt!=totalBlackCnt) flag=false;
        return;
    }
    if(root->color==BLACK) cnt++;
    else{
        if(root->lchild && root->lchild->color==RED) flag=false;
        if(root->rchild && root->rchild->color==RED) flag=false;
    }
    //printf("val:%d color:%d cnt:%d\n",root->val,root->color,cnt);

    dfs(root->lchild,cnt);
    dfs(root->rchild,cnt);
}

int main()
{int k,n,val;
    scanf("%d",&k);
    while(k--){
        scanf("%d",&n);
        Node* root=nullptr;
        for(int i=0;i<n;i++){
            scanf("%d",&val);
            insert(root,val);
        }
        if(root->color==RED){
            printf("No\n");
            continue;
        }
        totalBlackCnt=0;//記錄從根結點到任意一個葉結點的簡單路徑上黑色結點的個數
        //此處計算最左端的路徑
        Node* p=root;
        while(p){
            if(p->color==BLACK) totalBlackCnt++;
            p=p->lchild;
        }
        flag=true;//初始化
        dfs(root,0);
        printf("%s\n",flag?"Yes":"No");
    }
    return 0;
}

【疑問】 按照我自己的想法,dfs()函數我是這麽寫的,然而這麽寫會有兩個測試點通不過!還沒搞清楚!!!
void dfs(Node* root,int cnt)
{
    if(root==nullptr) return;
    if(root->color==BLACK) cnt++;
    else{
        if(root->lchild && root->lchild->color==RED) flag=false;
        if(root->rchild && root->rchild->color==RED) flag=false;
    }
    if(root->lchild==nullptr && root->rchild==nullptr){
        if(cnt!=totalBlackCnt) flag=false;
    }
    //printf("val:%d color:%d cnt:%d\n",root->val,root->color,cnt);
    dfs(root->lchild,cnt);
    dfs(root->rchild,cnt);
}

1135 Is It A Red-Black Tree