题目描述
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{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
题解
题意理解:判断插入序列生成的二叉搜索树是否相同
方法一
- 下面是一种最容易想到的办法,即根据序列建树然后判断两树是否相同
- 需要实现的函数:建树插入函数、两数相等判断函数
插入函数:二叉搜索树的操作集之一
- 传入的树为空,递归退出条件,找到要插入的位置,新建结点并返回
- 否则向左右子树继续找插入位置,递归调用函数
- 当 item 等于 data 元素已存在,什么都不做直接返回原树
创建函数:每读入一个结点就插入到树里去,循环比对每一组数据是否为同一棵树
判断函数:只需将 03-树1 树的同构 中判断是否同构的函数稍作修改,去掉交换左右子树的部分即为判断两棵树是否相等的函数
#include <stdio.h>
#include <stdlib.h>
typedef struct TNode *BST;
struct TNode {
int data;
BST left;
BST right;
};
BST Insert(BST T, int item)
{
if (!T) {
T = (BST)malloc(sizeof(struct TNode));
T->data = item;
T->left = T->right = NULL;
} else {
if (item < T->data)
T->left = Insert(T->left, item);
else if (item > T->data)
T->right = Insert(T->right, item);
}
return T;
}
BST Create(int n)
{
int i, item;
BST T = NULL;
for (i = 0; i < n; i++) {
scanf("%d", &item);
T = Insert(T, item);
}
return T;
}
int Identify(BST T1, BST T2)
{
if (!T1 && !T2) return 1;
if ((!T1 && T2) || (T1 && !T2)) return 0;
if (T1 && T2 && T1->data != T2->data) return 0;
if (T1 && T2 && T1->data == T2->data)
return Identify(T1->left, T2->left) && Identify(T1->right, T2->right);
}
int main()
{
int i, n, l;
BST T1, T2;
scanf("%d", &n);
while (n != 0) {
scanf("%d", &l);
T1 = Create(n);
for (i = 0; i < l; i++) {
T2 = Create(n);
if (Identify(T1, T2)) printf("Yes\n");
else printf("No\n");
}
scanf("%d", &n);
}
return 0;
}
方法二
- 课程中给出的方法是只建一棵树,然后根据序列去判断是否与该树相同
- 需要在树的数据结构定义上加上一个 flag , 0 表示没出现过, 1 表示出现过
判别方法:在树中按顺序搜索序列中的每一个树
- 如果每次搜索所经过的结点在前面均出现过,则一致
- 如果某次搜索中遇到前面未出现的结点,则不一致
Check 函数:判断某一个结点一路搜索下来碰到的是不是都在前面出现过,如果有没有碰到过的就返回不一致
Identify 函数:首先判断队首元素,根结点是否一致,一致就 flag = 1 ,不一致就 flag = 0 。然后去逐个判断后面的结点是否插在正确的位置。要注意不能提前返回,不然会出现还有数据没读完就进入下一组数据的 bug 。
#include <stdio.h>
#include <stdlib.h>
typedef struct TNode *BST;
struct TNode {
int data;
BST left;
BST right;
int flag;
};
BST Insert(BST T, int item)
{
if (!T) {
T = (BST)malloc(sizeof(struct TNode));
T->data = item;
T->left = T->right = NULL;
T->flag = 0;
} else {
if (item < T->data)
T->left = Insert(T->left, item);
else if (item > T->data)
T->right = Insert(T->right, item);
}
return T;
}
BST Create(int n)
{
int i, item;
BST T = NULL;
for (i = 0; i < n; i++) {
scanf("%d", &item);
T = Insert(T, item);
}
return T;
}
int Check(BST T, int item)
{
if (T->flag) {
if (item < T->data) return Check(T->left, item);
else if (item > T->data) return Check(T->right, item);
else return 0;
} else {
if (item == T->data) {
T->flag = 1;
return 1;
} else
return 0;
}
}
int Identify(BST T, int n)
{
int i, item, flag = 0;
scanf("%d", &item);
if (item != T->data) flag = 1;
else T->flag = 1;
for (i = 1; i < n; i++) {
scanf("%d", &item);
if ((!flag) && (!Check(T, item))) flag = 1;
}
if (flag) return 0;
else return 1;
}
void Reset(BST T)
{
if (T->left) Reset(T->left);
if (T->right) Reset(T->right);
T->flag = 0;
}
void Free(BST T)
{
if (T->left) Free(T->left);
if (T->right) Free(T->right);
free(T);
}
int main()
{
int i, n, l;
BST T;
scanf("%d", &n);
while (n != 0) {
scanf("%d", &l);
T = Create(n);
for (i = 0; i < l; i++) {
if (Identify(T, n)) printf("Yes\n");
else printf("No\n");
Reset(T);
}
Free(T);
scanf("%d", &n);
}
return 0;
}