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.

rbf1.jpgrbf2.jpgrbf3.jpg
Figure 1Figure 2Figure 3

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

C++:

建树过程中判断:

/*
 @Date    : 2018-03-07 08:39:51
 @Author  : 酸饺子 (changzheng300@foxmail.com)
 @Link    : https://github.com/SourDumplings
 @Version : $Id$
*/

/*
https://www.patest.cn/contests/pat-a-practise/1135
思路:
先根据先序遍历序列建BST树,如果建树的过程中发现不是BST则直接返回;
在建树的同时记录每个结点的黑高度,如果左右子树黑高度不等则表示条件4不满足
然后层序遍历判断条件4
 */

#include <iostream>
#include <cstdio>
#include <memory>
#include <cmath>
#include <queue>

using namespace std;

struct TNode
{
    int data;
    shared_ptr<TNode> left = nullptr, right = nullptr;
    int blackH = 0;
};

static bool isBST = true;
static bool isRB = true;

shared_ptr<TNode> build_tree(shared_ptr<TNode> T, int pre[], int preB, int preE)
{
    if (preB == preE || !isRB || !isBST) return T;
    int root = pre[preB];
    T = make_shared<TNode>();
    T->data = root;
    if (preB + 1 == preE)
    {
        if (T->data > 0) T->blackH = 1;
        return T;
    }
    int lLength = preE - preB - 1;
    for (int i = preB + 1; i != preE; ++i)
    {
        if (lLength == preE - preB - 1 && abs(pre[i]) > abs(root))
            lLength = i - preB - 1;
        if (lLength != preE - preB - 1)
        {
            if (abs(pre[i]) <= abs(root))
            {
                isBST = false;
                return T;
            }
        }
    }
    T->left = build_tree(T->left, pre, preB + 1, preB + 1 + lLength);
    T->right = build_tree(T->right, pre, preB + 1 + lLength, preE);
    int hl = T->left ? T->left->blackH : 0;
    int hr = T->right ? T->right->blackH : 0;
    if (hl != hr) isRB = false;
    else T->blackH = T->data > 0 ? hl + 1 : hl;
    return T;
}

bool judge(shared_ptr<TNode> T)
{
    if (!isBST || !isRB || T->data < 0) return false;
    queue<shared_ptr<TNode>> Q;
    Q.push(T);
    while (!Q.empty())
    {
        auto node = Q.front(); Q.pop();
        if (node->left)
        {
            if (node->data < 0 && node->left->data < 0) return false;
            Q.push(node->left);
        }
        if (node->right)
        {
            if (node->data < 0 && node->right->data < 0) return false;
            Q.push(node->right);
        }
    }
    return true;
}

int main(int argc, char const *argv[])
{
    int K, N;
    scanf("%d", &K);
    while (K--)
    {
        scanf("%d", &N);
        int pre[N];
        for (int i = 0; i != N; ++i)
            scanf("%d", &pre[i]);
        shared_ptr<TNode> T = nullptr;
        isBST = isRB = true;
        T = build_tree(T, pre, 0, N);
        if (judge(T)) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

后序遍历计算黑高度判断:

/*
 @Date    : 2018-09-05 23:10:38
 @Author  : 酸饺子 (changzheng300@foxmail.com)
 @Link    : https://github.com/SourDumplings
 @Version : $Id$
*/

/*
https://pintia.cn/problem-sets/994805342720868352/problems/994805346063728640
 */

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int K;
const int MAXN = 35;
int pre[MAXN];

struct TreeNode
{
    TreeNode() = default;
    TreeNode(int k, bool black_): key(k), black(black_) {}
    int key;
    bool black = true;
    int blackHeight = -1;
    TreeNode *left = nullptr, *right = nullptr;
};

TreeNode* build_tree(int b, int e)
{
    if (e == b)
        return nullptr;
    int k = pre[b];
    bool black = true;
    if (k < 0)
    {
        k = -k;
        black = false;
    }
    TreeNode *r = new TreeNode(k, black);
    if (b + 1 == e)
        return r;
    int leftE = e;
    for (int i = b + 1; i != e; ++i)
    {
        if (abs(pre[i]) >= k)
        {
            leftE = i;
            break;
        }
    }
    r->left = build_tree(b+1, leftE);
    r->right = build_tree(leftE, e);
    return r;
}

int get_black_height(TreeNode *r)
{
    int ret = 0;
    if (r)
    {
        if (r->blackHeight != -1)
            ret = r->blackHeight;
        else
        {
            int lH = get_black_height(r->left);
            int rH = get_black_height(r->right);
            if (lH != rH)
                ret = -2;
            else
            {
                if (r->black)
                {
                    ret = lH + 1;
                }
                else
                {
                    ret = lH;
                }
            }
        }
    }
    return ret;
}

bool post_order_traversal(TreeNode *T)
{
    bool ret = true;
    if (T)
    {
        bool ret1 = post_order_traversal(T->left);
        bool ret2 = post_order_traversal(T->right);
        T->blackHeight = get_black_height(T);
        if (T->blackHeight == -2)
            ret = false;
        else
        {
            if (!T->black && ((T->left && !T->left->black) || (T->right && !T->right->black)))
                ret = false;
            else
            {
                ret = ret1 && ret2;
            }
        }
    }
    return ret;
}

bool judge(TreeNode *T)
{
    bool ret = true;
    if (!T->black)
        ret = false;
    else
    {
        ret = post_order_traversal(T);
    }
    return ret;
}

int main()
{
    scanf("%d", &K);
    while (K--)
    {
        int N;
        scanf("%d", &N);
        TreeNode *T = nullptr;
        for (int i = 0; i != N; ++i)
            scanf("%d", &pre[i]);
        T = build_tree(0, N);
        if (judge(T))
        {
            printf("Yes\n");
        }
        else
        {
            printf("No\n");
        }
    }
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值