7-10 树的同构(25 point(s))
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。

图1
图2
输入格式:
输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。
输出格式:
如果两棵树是同构的,输出“Yes”,否则输出“No”。
输入样例1(对应图1):
8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -
输出样例1:
Yes
输入样例2(对应图2):
8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4
输出样例2:
No code:
#include <stdio.h> #include <string.h> struct TNode{ char Data;//字母 int Left,Right;//左右儿子编号 };//建立树的结构体 typedef struct TNode Tree;//typedef简化名称 Tree t1[12],t2[12];//两棵树的数组用于比较 int Read(Tree t[]){ int i; int n;//节点个数 int pre[12];//祖先数组,用于判断树根 int root = -1;//树根标号,初始化为-1 memset(pre,0,sizeof(pre)) ; scanf("%d",&n); if(n){//如果n不为零执行 for(i = 0; i < n; i++){ char l,r;//记录左右儿子的值 scanf(" %c %c %c",&t[i].Data,&l,&r); if(l!='-'){ t[i].Left = l-'0';//如果是数字,左子树记录该数字 pre[t[i].Left] = 1;//表示这个左孩子编号有父亲 } else{ t[i].Left = -1; } if(r!='-'){//右边同理 t[i].Right = r-'0'; pre[t[i].Right] = 1; } else{ t[i].Right = -1; } } }//记录完毕 //找根 for(i = 0; i < n; i++){ if(!pre[i]){//如果有节点父亲是0,说明没父亲为树根 root = i; break; } } return root; } int isSame(int root1,int root2){ if((root1 == -1) && (root2 == -1)){//树根都是空,同构返回1 return 1; } if(((root1 == -1) && (root2 != -1)) || ((root1 != -1) && (root2 == -1))){//如果一个是空一个不空,不同构,返回0 return 0; } if((t1[root1].Data) != (t2[root2].Data)){//如果树根值不同,不同构,返回0 return 0; } if((t1[root1].Left == -1) && (t2[root2].Left == -1)){//如果左子树都是空的,判断右子树 return isSame(t1[root1].Right,t2[root2].Right); } if((t1[root1].Left != -1) && (t2[root2].Left != -1) && (t1[t1[root1].Left].Data == t2[t2[root2].Left].Data)){//如果左树不空且左子树值想同,判断其左右子树 return (isSame(t1[root1].Left,t2[root2].Left) && isSame(t1[root1].Right,t2[root2].Right)); } else{//如果左子树有一个空的,或者两个树不空 左子树的值不同 ,交换左右子树判断 return (isSame(t1[root1].Left,t2[root2].Right) && isSame(t1[root1].Right,t2[root2].Left)); } } int main(){ int root1,root2;//树根节点编号 root1 = Read(t1);//读取 root2 = Read(t2); if(isSame(root1,root2))//判断是否同构 printf("Yes\n"); else printf("No\n"); return 0; }