是否同一棵二叉搜索树 (25 分)

本文探讨了如何判断多个插入序列是否能生成相同的二叉搜索树,提供了三种解题思路:构建并比较树结构,无需建树直接对比序列,以及构建一次树多次验证序列一致性,附带代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{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;
}
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值