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
鸣谢青岛大学周强老师补充测试数据!
代码长度限制:16 KB 时间限制:400 ms 内存限制:64 MB
题目解析:
关键点1:构建二叉搜索树,主要考察向二叉搜索树中插入元素
递归插入思想,(1)插入元素的数值小于根结点数值,则向根结点左子树中插入;(2)插入元素的数值大于根结点的数值,则向根结点右子树中插入;
关键点2:比较两棵二叉搜索树是否相同
递归比较思想,(1)若两棵二叉搜索树均为空,则视为相同的两棵二叉搜索树;(2)若两棵二叉搜索树在根结点相同的情况下,左子树和右子树分别对应相同,则视为相同的两棵二叉搜索树;
参考代码:
# include<stdio.h>
# include<stdlib.h>
# include<stdbool.h>
// 树结点结构
typedef struct TreeNode* Tree;
struct TreeNode{
int data;
Tree left;
Tree right;
};
Tree InsertTree(Tree tree, int data);
bool IsSameTree(Tree tree1, Tree tree2);
void Game(int N,int L);
void FreeTree(Tree tree);
int main(){
int N,L;
scanf("%d",&N);
// N为0表示输入结束
while(N!=0){
scanf("%d",&L);
// 一组检查的结果输出
Game(N,L);
scanf("%d",&N);
}
return 0;
}
// 一组检查
void Game(int N,int L){
// 创建一个初始树
Tree tree = NULL;
// 向初始树中插入元素
int i,j,data;
for(i=0;i<N;i++){
scanf("%d",&data);
tree = InsertTree(tree,data);
}
// 接收需要检查的序列
for(i=0;i<L;i++){
Tree tmp = NULL;
// 插入元素
for(j=0;j<N;j++){
scanf("%d",&data);
tmp = InsertTree(tmp,data);
}
// 判读是否是同一棵树并输出结果
if(IsSameTree(tree,tmp))printf("Yes\n");
else printf("No\n");
// 检查完毕后释放
FreeTree(tmp);
}
// 释放初始树
FreeTree(tree);
return;
}
// 二叉搜索树的插入
Tree InsertTree(Tree tree, int data){
if(tree==NULL){
// 如果为空树,则创建根结点
tree = (Tree)malloc(sizeof(struct TreeNode));
tree->data = data;
tree->left = tree->right = NULL;
}else{
// 递归插入
if(data<tree->data){
// 插入左子树
tree->left = InsertTree(tree->left,data);
}else if(data>tree->data){
// 插入右子树
tree->right = InsertTree(tree->right,data);
}
}
return tree;
}
// 判断是否是同一棵树
bool IsSameTree(Tree tree1, Tree tree2){
// 如果根结点都为空,则是一棵树
if(tree1==NULL && tree2==NULL)return true;
// 如果一个根结点为空,另一个不为空,则肯定不是
if(tree1==NULL && tree2 || tree1 && tree2==NULL)return false;
// 如果根结点不同,则肯定不是
if(tree1->data != tree2->data)return false;
// 递归判读其左子树与右子树是否是同一棵树
if(IsSameTree(tree1->left,tree2->left) && IsSameTree(tree1->right,tree2->right))return true;
else return false;
}
// 递归释放树
void FreeTree(Tree tree){
if(tree->left)FreeTree(tree->left);
if(tree->right)FreeTree(tree->right);
free(tree);
}