1135 Is It A Red-Black Tree (30point(s)) - C语言 PAT 甲级

1135 Is It A Red-Black Tree (30point(s))

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.
    figure1figure2figure3
    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 颗二叉搜索树,每棵树 N 个节点,并给出先序遍历,负号表示红色节点

判断是否是红黑树,红黑树需满足:

  1. 所有节点都是红色或黑色
  2. 根节点黑色
  3. 所有叶子节点 (NULL) 是黑色
  4. 如果节点为红色,两个孩子节点必须为黑色
  5. 每个节点,从该节点到达其可达的叶子节点的所有路径,包含相同数目的黑色节点
设计思路:
  1. 因为是二叉搜索树,且给了先序序列,所以可以直接建立一颗二叉搜索树
  2. 判断题目所给红黑树需满足的条件,仅需判断 2、4、5 条件
    1. 判断 2:根节点为黑
    2. 判断 4:节点为红,孩子节点为黑
    3. 判断 5:递归判断每个节点到叶子节点包含的黑节点个数

注意:

  • 最开始把 root 放在了循环外,而且没实现释放树的内存,导致所有树都建在了第一颗树上
  • 本代码中未释放的申请内存,在运行期间会一直存在,循环内不释放,每次循环都会丢失 root 地址信息
  • 当然,程序结束后,本程序的所有内存会被操作系统回收,但实际千万不要依赖此特点
编译器:C (gcc)
#include <stdio.h>
#include <stdlib.h>

struct node {
        int data, red;
        struct node *left, *right;
};

struct node *build(struct node *root, int a)
{
        if (root == NULL) {
                root = (struct node *)malloc(sizeof(struct node));
                root->data = abs(a);
                root->red = a < 0 ? 1 : 0;
                root->left = NULL;
                root->right = NULL;
        } else if (abs(a) <= root->data) {
                root->left = build(root->left, a);
        } else {
                root->right = build(root->right, a);
        }
        return root;
}

int judge4(struct node *root)
{
        if (root == NULL)
                return 1;
        if (root->red) {
                if (root->left != NULL && root->left->red)
                        return 0;
                if (root->right != NULL && root->right->red)
                        return 0;
        }
        return judge4(root->left) && judge4(root->right);
}

int max(int a, int b)
{
        return a >= b ? a : b;
}

int get_sum(struct node *root)
{
        if (root == NULL)
                return 0;
        int l = get_sum(root->left);
        int r = get_sum(root->right);
        return root->red ? max(l, r) : max(l, r) + 1;
}

int judge5(struct node *root)
{
        if (root == NULL)
                return 1;
        int l = get_sum(root->left);
        int r = get_sum(root->right);
        if (l != r)
                return 0;
        return judge5(root->left) && judge5(root->right);
}

void free_tree(struct node *root)
{
        if  (root == NULL)
                return ;
        free_tree(root->left);
        free_tree(root->right);
        free(root);
}

int main(void)
{
        int k, n;
        int i, a;

        scanf("%d", &k);
        while (k--) {
                struct node *root = NULL;//不能放在循环外
                scanf("%d", &n);
                for (i = 0; i < n; i++) {
                        scanf("%d", &a);
                        root = build(root, a);
                }
                if (root->red || judge4(root) == 0 || judge5(root) == 0)
                        printf("No\n");
                else
                        printf("Yes\n");

                //free_tree(root);
                //未实现 free_tree(root);//释放内存
        }
        return 0;
}
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值