本文是依据陈越、何钦铭在中国大学MOOC网上第三讲《树》中的小白专场《如何判别两二叉树同构》而撰成。
https://www.icourse163.org/learn/ZJU-93001?tid=1207006212#/learn/content?type=detail&id=1212031634&cid=1215166211
题目描述:
课程中采用结构数组构成的静态链表来实现这道题,A、B、C等这些结点在数组中的存储形式如下:
其中Left,Right表示其对应结点的左儿子、右儿子在数组中的下标,若Left或Right的值为-1,则表示该结点没有左儿子或右儿子,若Left值为2,则表示该结点的左儿子存在结构数组中下标为2的空间中。
程序的实现主要依据两个函数,一是BuilTree(),其作用是根据输入的值构建一棵二叉树,并返回二叉树的根结点在结构数组中的下标值;一是Isomorphic(),其作用是根据BuilTree返回的两棵二叉树根节点的值,比较两棵二叉树是否同构。
完整程序如下:
#include <iostream>
#define MaxTree 10
#define Null -1
using namespace std;
typedef char ElementType;
struct TreeNode
{
ElementType Element;
int Left;
int Right;
}T1[MaxTree],T2[MaxTree];
int main()
{
int BuildTree(TreeNode T[]);
int Isomorphic(int R1,int R2);
int R1,R2;
R1=BuildTree(T1);
R2=BuildTree(T2);
if(Isomorphic(R1,R2))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
return 0;
}
int BuildTree(TreeNode T[])
{
int N,i,Root;
cout<<"N=";
cin>>N;
int check[N];
ElementType cl,cr;
if(N){
for(i=0;i<N;i++) check[i]=0;
for(i=0;i<N;i++){
cin>>T[i].Element>>cl>>cr;
if(cl!='-'){
T[i].Left=cl-'0';
check[T[i].Left]=1;
}
else
T[i].Left=Null;
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; //记Root为根节点在数组中的下标
}
return(Root);
}
int Isomorphic(int R1,int 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));
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(T1[R1].Right,T2[R2].Right));
else //左边跟右边同构,右边跟左边同构
return(Isomorphic(T1[R1].Left,T2[R2].Right) && Isomorphic(T1[R1].Right,T2[R2].Left));
}