题目
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{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:(建树)
此题最简单的思路就是,先创建一个原树,之后输入的数据用一个临时变量Tree temp来保存,之后用一个函数来判断这两棵树是否相等。判断的方法就是,如果两棵树的根结点都为空,则相等。如果两个树的根结点有一个为空则不相等。如果两个树的根结点都存在,看其是否相等,不相等返回false,相等则递归调用该函数判断其左右孩子结点是否一样。
代码1:
#include <iostream>
using namespace std;
struct Node{
int data;
Node * left;
Node * right;
};
typedef Node* Tree;
Tree insert(Tree BT,int x){//创建树
if(!BT){
BT=new(Node);
BT->data=x;
BT->left=BT->right=NULL;
}
else if(x<BT->data)
BT->left=insert(BT->left,x);
else if(x>BT->data)
BT->right=insert(BT->right,x);
return BT;
}
bool judgeidentical(Tree a,Tree b){//判断两棵树是否一致
if(a==NULL&&b==NULL)
return true;
else if((a!=NULL&&b==NULL)||(a==NULL&&b!=NULL))
return false;
else if(a->data==b->data)
return judgeidentical(a->left,b->left)&&judgeidentical(a->right,b->right);
return false;
}
int main(){
int n,l,x;
while(cin>>n&&n){
cin>>l;
Tree BT=NULL;
for(int i=0;i<n;i++){
cin>>x;
BT=insert(BT,x);
}
for(int i=0;i<l;i++){
Tree temp=NULL;
for(int i=0;i<n;i++){
cin>>x;
temp=insert(temp,x);
}
judgeidentical(temp,BT)?cout<<"Yes"<<endl:cout<<"No"<<endl;
}
}
return 0;
}
思路2 :(不建树)
不建树的话:
3 1 2 4
3 4 1 2
3 2 4 1
比较第一个数,即根结点是否相同。相同,然后根据根结点,划分成两堆,左堆比根结点小,右堆比根结点大。然后比较两个的左子树和右子树是否一致。
{1 2} 3 {4}
{1 2} 3 {4}
{2 1} 3 {4}
可以看出第三个跟其他两个不一样,所以No
思路3:(建一棵树,比较其他序列与该树是否一致)
比方说原树是3 1 4 2
那么在建好的树中按顺序搜索序列3 2 4 1中的每个数
如果每次搜索所经过的结点在前面均出现过,则一致
否则(某次搜索中遇到前面未经出现过的结点),则不一致。
比如过在3241的遍历过程当中,2开始遍历树寻找的时候,会碰到1,但是1之前没有被访问过,所以两个树不一致。
代码3
#include <iostream>
using namespace std;
struct Node{
int data;
Node * left;
Node * right;
int flag;
};
typedef Node* Tree;
Tree insert(Tree BT,int x){
if(!BT){
BT=new(Node);
BT->data=x;
BT->left=BT->right=NULL;
BT->flag=0;
}
else if(x<BT->data)
BT->left=insert(BT->left,x);
else if(x>BT->data)
BT->right=insert(BT->right,x);
return BT;
}
bool check(Tree T,int x){
if(T->flag){
if(x<T->data)
return check(T->left,x);//虽然说任何arrow前面都得加入是否判断该地址是否为NULL,但是x的个数其实就是结点个数
else if(x>T->data)
return check(T->right,x);
else
return false;
}
else{
if(x==T->data){
T->flag=1;
return true;
}
else
return false;
}
}
void reset(Tree T){//每次标记要清0
if(T->left)
reset(T->left);
if(T->right)
reset(T->right);
T->flag=0;
}
int main(){
int n,l,x;
while(cin>>n&&n){
cin>>l;
Tree BT=NULL;
for(int i=0;i<n;i++){
cin>>x;
BT=insert(BT,x);
}
for(int i=0;i<l;i++){
bool judge=true;
reset(BT);
for(int i=0;i<n;i++){
cin>>x;
if(!check(BT,x))
judge=false;
}
judge?cout<<"Yes"<<endl:cout<<"No"<<endl;
}
}
return 0;
}