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.
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 个节点,并给出先序遍历,负号表示红色节点
判断是否是红黑树,红黑树需满足:
- 所有节点都是红色或黑色
- 根节点黑色
- 所有叶子节点 (NULL) 是黑色
- 如果节点为红色,两个孩子节点必须为黑色
- 每个节点,从该节点到达其可达的叶子节点的所有路径,包含相同数目的黑色节点
设计思路:
- 因为是二叉搜索树,且给了先序序列,所以可以直接建立一颗二叉搜索树
- 判断题目所给红黑树需满足的条件,仅需判断 2、4、5 条件
- 判断 2:根节点为黑
- 判断 4:节点为红,孩子节点为黑
- 判断 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;
}