数据结构与算法——判断是否为同一棵二叉树

一、如何判断两棵树是否同构

两棵树同构:对于两棵树,比较相对应的结点,如果该结点下的左右子树完全相同,且考虑左右互换,对于每个结点都是如此
下面是浙大何老师课上的PPT:
图一
二叉树表示:
和一般的二叉树不同,这里为了方便比较二叉树的不同,采用了静态链表存储,即物理存储结构是数组,但具有链表的灵活性,通过数组下标链接下一个结点

struct TreeNode
{
ElementType Element;
Tree Left;
Tree Right;
}T1[MaxTree],T2[MaxTree];

二、代码实现:

#include<iostream>
using namespace std;
#define MaxTree 10
#define ElementType char
#define Tree int
#define Null -1 //std中的NULL默认为0,而0为数组的第一个下标

struct TreeNode
{
    ElementType Element;
    Tree Left;
    Tree Right;
}T1[MaxTree],T2[MaxTree];

Tree BuildTree(struct TreeNode T[])
{
    ElementType cl,cr;
    Tree N,Root,check[10],i;//Root是结构数组的下标,也是根节点的下标
    cin >> N;//输入树的元素个数
    if(N)
    {
        for(i=0;i<N;i++) check[i] = 0;//check数组用来记录哪一个结点没有被其他结点指过,说明该结点是根节点,初始化为0,表示全未被指过
        for(i=0;i<N;i++)//遍历N次,从数组下标开始
        {
            cin >>T[i].Element;//cl,cl是char型的左右值,还要转换成整型
            cin >> cl;
            cin >> cr;
            if(cl!='-')//输入‘-’说明其左子节点非空
            {
                T[i].Left = cl-'0';//类型转换成整型
                check[T[i].Left] = 1;//说明这个结点被指过,不能是根结点
            }
            else T[i].Left = Null;//子节点为空,其左右值设为-1
            if(cr!='-')//输入‘-’说明其左子节点非空
            {
                T[i].Right = cr-'0';//类型转换成整型
                check[T[i].Right] = 1;//说明这个结点被指过,不能是根结点
            }
            else T[i].Right = Null;
        }
        for(i=0;i<N;i++)
                if(!check[i]) break;//遍历,直到直到找到根节点
        Root = i;
    }
    return Root;
}


int Isomorphic(Tree R1,Tree R2)
{
    //第一个树且第二个树都为空,返回相同
    if((R1==Null)&&(R2==Null)) return 1;
    //第一个结点空,第二个非空或者反之,返回不同
    if(((R1==Null)&&(R2!=Null)) || ((R1!=Null)&&(R2==Null)))
        return 0;
    //结点元素不相同
    if(T1[R1].Element!=T2[R2].Element) return 0;
    //左子树均为空,则继续判断右子树
    if((T1[R1].Left==Null)&&T2[R2].Left==Null)
        return Isomorphic(T1[R1].Right,T2[R2].Right);
    //左子树均非空,且元素相同,则需继续判断其根节点的左右子树,这里为什么不对其右子树直接判断?是因为return语句进行递归的过程中会对其右子树进行判断,在此判断多此一举
    if(((T1[R1].Left!=Null)&&(T2[R2].Left!=Null))&&
        ((T1[T1[R1].Left].Element==T2[T2[R2].Left].Element)))
        return (Isomorphic(T1[R1].Left,T2[R2].Left)&&//判断其左子树
                Isomorphic(T2[R1].Right,T2[R2].Right));//判断其右子树
    else//否则则可能是对称同构,需要进一步判断是否左=右,和右=左
        return (Isomorphic(T1[R1].Left,T2[R2].Right)&&
                Isomorphic(T1[R1].Left,T2[R2].Left));
}







int main()
{
    Tree R1,R2;
    R1 = BuildTree(T1);//建立第一棵结构数组二叉树
    R2 = BuildTree(T2);//第二棵
    cout << R1<<endl;
    cout << R2<<endl;
    if(Isomorphic(R1,R2)) cout << "Yes"<<endl;//判断是否同构
    else cout<<"No"<<endl;
    return 0;
}

这里我进行两次比较:在这里插入图片描述
第一次:是图二的上下两个数组,对应的二叉树也画在了右边,这两棵树明显同构,再来看看代码跑出来的结果:
在这里插入图片描述
没错!
再来看看图二的下面两棵树:明显对于A结点,即使交换左右子树,也不是同一颗二叉树,对于B结点,是对称同构的,所以整个一棵树并非是同构的,看代码结果:
在这里插入图片描述
Bingo!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生参加学科竞赛有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞赛是提高专业知识和技能水平的有效途径。通过参与竞赛,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞赛过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞赛培养了学生的团队合作精神。许多竞赛项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞赛是提高学生综合能力的一种途径。竞赛项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参赛者具备全面的素质。在竞赛过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞赛可以为学生提供展示自我、树立信心的机会。通过比赛的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞赛对于个人职业发展具有积极的助推作用。在竞赛中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞赛奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值