题目描述
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。
输入格式
输入包含若干组测试数据。每组数据的第1行给出两个正整数N (≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。随后L行,每行给出N个插入的元素,属于L个需要检查的序列。
简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。
方法
原理:遍历同一棵二叉树,经过的路线是一样的
代码实现(pta提交正确)
#include <stdio.h>
#include <malloc.h>
typedef struct node *tree;
tree lnsert(tree t,int v);
tree newgz(int v);
struct node{
int V;//该结点值的大小
tree left,right;
int flag;//在判断是否为同一个二叉搜索树的时候用来标记该节点是否被访问过
};
/*建搜索树*/
tree gz(int n){
tree t;
int i,v;
scanf("%d",&v);
t=newgz(v);//构造一个新的节点
for(i=1;i<n;i++){
scanf("%d",&v);
t=lnsert(t,v);//把后续的结点按二叉搜索树的特点插进t
}
return t;
}
/*构造一个结点*/
tree newgz(int v){
tree t=(tree)malloc(sizeof(struct node));
t->V=v;
t->left=t->right=NULL;
t->flag=0;
return t;
}
/*将一个结点插入二叉搜索树*/
tree lnsert(tree t,int v){
if(!t) t=newgz(v);
else{
if(v>t->V) t->right=lnsert(t->right,v);
else t->left=lnsert(t->left,v);
}
return t;
}
int dpd(tree t,int v){
if(t->flag){//如果该节点之前访问过了 ,则去左边或右边去找
if(v<t->V) return dpd(t->left,v);
else if(v>t->V) return dpd(t->right,v);
else return 0;//如果相等 ,有意味在这个序列里面,有一个数出现2次,不符合二叉搜索树的定义,
}
else{//如果该节点之前没被访问过并且就是我们要找的点,则符合,并将flag设为
if(v==t->V){
t->flag=1;
return 1;
}
else return 0; //如果该节点之前没被访问过而且又不是我们要找的 ,说明这个个结点是之前未出现的结点,则不是
}
}
int qpd(tree t,int n){
int i,v,flag=0;//0表示一致,1表示不一致
scanf("%d",&v);
if(v!=t->V) flag=1;//第一个为根结点的值,如果根结点的值不同,则不会是同一棵二次手术
else t->flag=1;//根结点已经访问,flag设为1
for(i=1;i<n;i++){
scanf("%d",&v);
if((!flag)&&(!dpd(t,v))) flag=1;
}
if(flag) return 0;
return 1;
}
void resetf(tree t){
if(t->left) resetf(t->left);
if(t->right) resetf(t->right);
t->flag=0;
}
void freet(tree t){
if(t->left) freet(t->left);
if(t->right) freet(t->right);
free(t);
}
int main(){
int n,l,i;
tree t;
scanf("%d",&n);
while(n){//n为0,程序退出
scanf("%d",&l);
t=gz(n);//建树
for(i=0;i<l;i++){//输入l列,判断跟树是不是同一棵树
if(qpd(t,n)) printf("Yes
");
else printf("No
");
resetf(t);//清除t中的标记flag,使其都为0
}
freet(t);//把树释放掉
scanf("%d",&n);
}
}