树的同构

7-1 树的同构 (30 point(s))

给定两棵树T1和T2。若是T1能够经过若干次左右孩子互换就变成T2,则咱们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,由于咱们把其中一棵树的结点A、B、G的左右孩子互换后,就获得另一棵树。而图2就不是同构的。node


 

图1ios

图2数组

现给定两棵树,请你判断它们是不是同构的。

输入格式:框架

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤),即该树的结点数(此时假设结点从0到N1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。若是孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每一个结点中存储的字母是不一样的。ide

 

先从大的框架主函数写起,先无论怎么实现先大胆用各类函数函数

方法:先创建两棵树并返回根结点,再判断返回结果,根据结果输出yes或noflex

int main() { int root1,root2; root1=input(t1);  //接收数据生成一棵树并返回根结点的标号 
    root2=input(t2); if(match(root1,root2)) //调用函数返回判断结果 
       cout<<"Yes"; else cout<<"No"; return 0; }
main

先把结点的定义肯定下来spa

方法:字符型的数据,整型的左右孩子code

typedef struct { char data; int lchild,rchild; }node; //根据题意定义一个结构体放0-n号结点的信息(字母及左右孩子的标号) 
struct

创建树blog

方法:这个就是老套路了,按照编号(下标)输入数据和孩子编号,更改孩子结点的flag值,最后遍历全部结点来找出根节点

int input(node t[]) { //输入数据并返回根结点的标号 
    int n; char ch1,ch2; cin>>n;  //输入一棵树总共结点数 
    if(n==0) return -1;  //若是是空树就直接返回 不一样构了 
    bool test[n]={false};  //定义一个布尔数组来标记每一个结点是否有双亲 
    for(int i=0;i<n;i++) { //从0开始读入对应标号的结点的信息 
        cin>>t[i].data; cin>>ch1>>ch2; if(ch1!='-') { //若是左孩子不为空就成为对应结点的左孩子 
            t[i].lchild=ch1-'0'; test[ t[i].lchild ]=true;  //左孩子标号的那个结点就是有双亲的了 
 } else t[i].lchild=-1;  //左孩子为空则标记为-1 
        if(ch2!='-') { t[i].rchild=ch2-'0'; test[ t[i].rchild ]=true; } else t[i].rchild=-1; } for(int j=0;j<n;j++) { //从0开始逐一判断每一个结点是否有双亲 
        if(!test[j])  //没有双亲的就是根结点 
        return j; } }
input

比较判断是否同构

方法:分两种状况来讨论

树空的状况1.两棵树都为空 (同构)  2.一棵树为空另外一棵树不为空 (不一样构)

树不为空的状况1.结点的数据不相等(不一样构)  2.结点数据相等继续比较左左孩子和右右孩子(若都同构则两棵树同构)  3.结点数据相等但左左孩子和右右孩子不一样构则继续比较左右和右左孩子(若都同构则两棵树同构)  4.结点数据相等但左左右右,左右右左都不一样构则两棵树不一样构

int match(int r1,int r2) { //判断是否同构 
    if(r1==-1&&r2==-1) return 0;//若是两棵树都为空则不一样构 
    if((r1==-1&&r2!=-1) || (r1!=-1&&r2==-1)) return 0;  //两棵树一棵为空,一棵不为空则不一样构 
    if(t1[r1].data!=t2[r2].data) return 0;  //若是非空但数据不相等则不一样构 
    if(match(t1[r1].lchild,t2[r2].lchild) && match(t1[r1].rchild,t2[r2].rchild)) return 1;  //若是非空且数据相等则继续比较左左 右右 
    if(match(t1[r1].lchild,t2[r2].rchild) && match(t1[r1].rchild,t2[r2].lchild)) return 1;  //若是非空且数据相等但左左右右不相等则比较左右 右左 
    
    return 0;  //以上包含了空的状况和非空时同构的状况最后加上不一样构的时候 
}
match

最后贴上所有代码

#include <iostream>
using namespace std; typedef struct { char data; int lchild,rchild; }node; //根据题意定义一个结构体放0-n号结点的信息(字母及左右孩子的标号) 
 node t1[11],t2[11];  //定义两个结构体类型的数组 
 
int input(node t[]) { //输入数据并返回根结点的标号 
    int n; char ch1,ch2; cin>>n;  //输入一棵树总共结点数 
    if(n==0) return -1;  //若是是空树就直接返回 不一样构了 
    bool test[n]={false};  //定义一个布尔数组来标记每一个结点是否有双亲 
    for(int i=0;i<n;i++) { //从0开始读入对应标号的结点的信息 
        cin>>t[i].data; cin>>ch1>>ch2; if(ch1!='-') { //若是左孩子不为空就成为对应结点的左孩子 
            t[i].lchild=ch1-'0'; test[ t[i].lchild ]=true;  //左孩子标号的那个结点就是有双亲的了 
 } else t[i].lchild=-1;  //左孩子为空则标记为-1 
        if(ch2!='-') { t[i].rchild=ch2-'0'; test[ t[i].rchild ]=true; } else t[i].rchild=-1; } for(int j=0;j<n;j++) { //从0开始逐一判断每一个结点是否有双亲 
        if(!test[j])  //没有双亲的就是根结点 
        return j; } } int match(int r1,int r2) { //判断是否同构 
    if(r1==-1&&r2==-1) return 0;//若是两棵树都为空则不一样构 
    if((r1==-1&&r2!=-1) || (r1!=-1&&r2==-1)) return 0;  //两棵树一棵为空,一棵不为空则不一样构 
    if(t1[r1].data!=t2[r2].data) return 0;  //若是非空但数据不相等则不一样构 
    if(match(t1[r1].lchild,t2[r2].lchild) && match(t1[r1].rchild,t2[r2].rchild)) return 1;  //若是非空且数据相等则继续比较左左 右右 
    if(match(t1[r1].lchild,t2[r2].rchild) && match(t1[r1].rchild,t2[r2].lchild)) return 1;  //若是非空且数据相等但左左右右不相等则比较左右 右左 
    
    return 0;  //以上包含了空的状况和非空时同构的状况最后加上不一样构的时候 
} int main() { int root1,root2; root1=input(t1);  //接收数据生成一棵树并返回根结点的标号 
    root2=input(t2); if(match(root1,root2)) //调用函数返回判断结果 
       cout<<"Yes"; else cout<<"No"; return 0; }
相关文章
相关标签/搜索