TOP

1135. Is It A Red-Black Tree-PAT甲级

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 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

分析:

这道题一开始使用先序不建树测试点1过不去,找了好久问题发现不建树不适合有重复节点的树,这是因为不建树去遍历一棵树时中序序列的下标并不是唯一的,会导致子树的划分出现错误,从而陷入无限循环,提交代码测试点1段错误,由此推断测试点1数据可能有重复节点。

建树AC,先建树再DFS遍历树,judgeRBT两个参数分别是,root与父节点颜色par_color。使用par_color将连续两个节点是否都为红色与根节是否红色合成一个判断条件,初始将父节点的颜色设置为-1即红色,如果根节点为红色则is2Red为true即有两个连续的红色则不为二叉树。记录每一条path上黑色节点的数目bnode,当到达叶子节点时将bnode黑色节点数目插入一个set即isRep,若所有path的bnode一致,则set的大小最终为1。最终DFS遍历完一棵树,得到is2Red与isRep.size()。is2Red==false&&isRep.size()==1时说明是一颗红黑树输出Yes。

建树AC代码

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
using namespace std;

set<int> isRep; //用来判断所有路径黑色节点个数是否一定
vector<int> pre;
int bnode, n, is2Red; //bnode记录某一路径黑色节点数,is2Red是否有两个连续的红色父子

struct Node
{
    int data;
    Node *lchild, *rchild;
    Node(int x) : data(x), lchild(NULL), rchild(NULL){};
};

void create(Node *&root, int v)
{
    if (root == NULL)
        root = new Node(v);
    else if (abs(v) <= abs(root->data))
        create(root->lchild, v);
    else
        create(root->rchild, v);
}

void judgeRBT(Node *root, int par_color)
{
    if (root == NULL)
    {
        isRep.insert(bnode);
        return;
    }
    if (root->data < 0 && par_color < 0)
        is2Red = true;
    if (root->data > 0)
        bnode++;
    judgeRBT(root->lchild, root->data);
    judgeRBT(root->rchild, root->data);
    if (root->data > 0)
        bnode--;
}

int main()
{
    int k;
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        scanf("%d", &n);
        isRep.clear();
        is2Red = false;
        bnode = 0;
        pre.resize(n);
        Node *root = NULL;
        for (int j = 0; j < n; j++)
        {
            scanf("%d", &pre[j]);
            build(root, pre[j]);
        }
        judgeRBT(root, -1);
        //若父子节点无连续红色且各个路径黑色节点一定时输出Yes
        printf("%s\n", ((!is2Red && (isRep.size() == 1)) ? "Yes" : "No"));
    }
    return 0;
}

不建树测试点1段错误代码

#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

set<int> isRep; //用来判断所有路径黑色节点个数是否一定
vector<int> pre, in;
int bnode, n; //用来记录某一路径黑色节点数
bool is2Red;  //检测是否有两个连续红色

void judgeRBTree(int par_color, int inl, int inr, int pre_root)
{
    if (inl <= inr)
    {
        if (par_color < 0 && pre[pre_root] < 0)
            is2Red = true;
        int in_root = 0;
        while (pre[pre_root] != in[in_root])
            in_root++;

        //如果左孩子是黑色则bnode++
        if (inl <= in_root - 1 && pre[pre_root + 1] > 0)
            bnode++;
        judgeRBTree(pre[pre_root], inl, in_root - 1, pre_root + 1);
        if (inl <= in_root - 1 && pre[pre_root + 1] > 0)
            bnode--;

        //如果右孩子是黑色则bnode++
        if (in_root + 1 <= inr && pre[in_root - inl + pre_root + 1] > 0)
            bnode++;
        judgeRBTree(pre[pre_root], in_root + 1, inr, in_root - inl + pre_root + 1);
        if (in_root + 1 <= inr && pre[in_root - inl + pre_root + 1] > 0)
            bnode--;
    }
    else
    {
        //将这一路径上的黑节点数插入rep
        isRep.insert(bnode);
        return;
    }
}

int main()
{
    int k;
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        scanf("%d", &n);
        isRep.clear();
        pre.resize(n);
        in.resize(n);
        is2Red = false;
        bnode = 0;
        for (int j = 0; j < n; j++)
        {
            scanf("%d", &pre[j]);
            in[j] = pre[j];
        }
        sort(in.begin(), in.end(), [](int a, int b) { return abs(a) < abs(b); });
        judgeRBTree(-1, 0, n - 1, 0);
        //若父子节点无连续红色且,各个路径黑色节点一定时输出Yes
        printf("%s\n", ((!is2Red && (isRep.size() == 1)) ? "Yes" : "No"));
    }
    return 0;
}
posted @ 2020-11-10 18:11  Laueks  阅读(131)  评论(0)    收藏  举报