04-树4 是否同一棵二叉搜索树 (25分)
题目描述
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。
输入格式
输入包含若干组测试数据。每组数据的第1行给出两个正整数N (≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。
简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。
输出格式
对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。
输入样例
4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0
输出样例
Yes
No
No
解题思路
对于每一波(输入样例有两波),先将N和L读进来,然后根据第一个序列构建二叉搜索树,最后将接下来的序列与该树做比较,判断是否是同一棵二叉搜索树。那么现在主要有两个问题,一个是通过序列构建二叉搜索树,另一个是将序列与已有的树做比较。对于第一个问题,先把第一个值作为根,然后读取后面的值。若待插入的值比当前结点的值小,则插入在左子树上;若待插入的值比当前结点的值大,则插入在右子树上,显然这可以通过一个递归函数实现。对于第二个问题,可以在树的结点中添加一个标志,当标志为1时代表该结点已经比较过了,当标志为0时代表该结点还没比较过。因此每读取一个值的时候就调用一次比较函数。该函数从根节点开始比较,在当前结点标志为0的情况下,若结点值等于读取值,则说明比较成功,否则比较失败;在当前结点标志为1的情况下,若读取值大于结点值则比较结点的右子树,若读取值小于结点值则比较结点的左子树,若相等则比较失败(因为结点值唯一),显然这也可以通过一个递归函数实现。
代码
#include <stdio.h>
#include <stdlib.h>
struct TreeNode {
int data;
int flag;
struct TreeNode *left;
struct TreeNode *right;
};
typedef struct TreeNode *Tree;
Tree makeTree(int n);
Tree newNode(int data);
Tree insert(Tree root, int data);
int judge(Tree root, int n);
int check(Tree root, int data);
void reset(Tree root);
void freeTree(Tree root);
int main() {
int N, L;
Tree root;
scanf("%d", &N);
while (N) {
scanf("%d", &L);
root = makeTree(N);
for (int i = 0; i < L; i++) {
if (judge(root, N)) printf("Yes\n");
else printf("No\n");
reset(root);
}
freeTree(root);
scanf("%d", &N);
}
return 0;
}
Tree makeTree(int n) {
Tree root;
int data;
scanf("%d", &data);
root = newNode(data);
for (int i = 1; i < n; i++) {
scanf("%d", &data);
root = insert(root, data);
}
return root;
}
Tree newNode(int data) {
Tree node = (Tree) malloc(sizeof(struct TreeNode));
node->data = data; node->flag = 0;
node->left = NULL; node->right = NULL;
return node;
}
Tree insert(Tree root, int data) {
if (!root) {
root = newNode(data);
} else if (data > root->data) {
root->right = insert(root->right, data);
} else if (data < root->data) {
root->left = insert(root->left, data);
}
return root;
}
int judge(Tree root, int n) {
int data, flag = 0;
scanf("%d", &data);
if (root->data != data) flag = 1;
else root->flag = 1;
for (int i = 1; i < n; i++) {
scanf("%d", &data);
if (!flag && !check(root, data)) flag = 1;
}
if (flag) return 0;
else return 1;
}
int check(Tree root, int data) {
if (root->flag) {
if (data > root->data) {
return check(root->right, data);
} else if (data < root->data) {
return check(root->left, data);
} else {
return 0;
}
} else {
if (data == root->data) {
root->flag = 1;
return 1;
} else {
return 0;
}
}
}
void reset(Tree root) {
if (root->left) reset(root->left);
if (root->right) reset(root->right);
root->flag = 0;
}
void freeTree(Tree root) {
if (root->left) freeTree(root->left);
if (root->right) freeTree(root->right);
free(root);
}