题目描述
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{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
解答
思路:
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到
1):建立两棵树
2):不建树的判别方法
树T{3,1,2,4}和{3,4,1,2}
分成比根节点小的和比根节点大的 按照原来的顺序
第一组 {1 2 }3 {4}
第二组 {1 2 }3 {4}
3):建立一颗树 再判别序列
方法:在树T中按照顺序搜索序列 3 2 4 1的每个数
- 如果每次搜索所经过的结点在前面均为出现过 则一致
- 否则(某次搜索中遇到前面未出现的结点) 则不一致
#include<iostream>
#include<malloc.h>
using namespace std;
//二叉搜索树的结构定义
typedef struct node *tree;
struct node{
int data;
tree Lchild;
tree Rchild;
int flag;//标记是否经过该结点
};
//构建新节点
tree NewNode(int data)
{
tree T=(tree)malloc(sizeof(struct node));
T->Lchild=T->Rchild=NULL;
T->data=data;
T->flag=0;
return T;
}
//二叉搜索树的插入
tree Insert(tree T,int data)
{
if(!T) T=NewNode(data);//如果是空树 就建立一个新节点
else{//递归找插入的位置
if(data>T->data) T->Rchild=Insert(T->Rchild,data);
else T->Lchild=Insert(T->Lchild,data);
}
return T;
}
//建立需要比较的二叉搜索树 N为建立节点的个数
tree BuildTree(int N)
{
tree T;
int data;
cin>>data;
T=NewNode(data);
for(int i=1;i<N;i++){
cin>>data;
T=Insert(T,data);
}
return T;
}
/*
按照顺序查找结点 如果经过的结点之前未经过 说明不是同一颗树
(因为结点本应该插在这个未经过的结点的位置 但现在却经过)
*/
int Check(tree T,int data)
{
if(T->flag){//flag==1表示访问过的点
if(data>T->data)Check(T->Rchild,data);
else if(data<T->data) Check(T->Lchild,data);
else return 0;//碰到了两个一样的值
}else{
if(data==T->data){
T->flag=1;
return 1;
}else return 0;//遇到了以前没遇到的点
}
}
int judge(tree T,int N)
{
int data,flag=0;//0表示目前符合一致
cin>>data;
if(T->data!=data) flag=1;//树根不一致
else T->flag=1;//根节点标记为1
for(int i=1;i<N;i++){
cin>>data;
if(!flag&&!Check(T,data))flag=1;//设置flag 原因是 即使判断了不是同一颗树 也要将剩下的结点接受完 防止影响下一组数据
}
if(flag) return 0;
else return 1;
}
//重设flag
void Reset(tree T)
{
if(T->Lchild) Reset(T->Lchild);
if(T->Rchild) Reset(T->Rchild);
T->flag=0;
}
//重设树
void FreeTree(tree T)
{
if(T->Lchild) FreeTree(T->Lchild);
if(T->Rchild) FreeTree(T->Rchild);
free(T);
}
int main()
{
int N,L;
tree T;
cin>>N;
while(N){
cin>>L;
T=BuildTree(N);
for(int i=0;i<L;i++){
if(judge(T,N)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
Reset(T);
}
FreeTree(T);
cin>>N;
}
return 0;
}