前言
在准备考研复习专业课数据结构,所以我在mooc平台上找了浙江大学的数据结构课程重新学习,感觉老师留的课后题都很有趣,所以想记录下自己的学习过程。
题目:
给定两棵树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):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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:
输入样例2(对应图2):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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:
题解
题目分析
对于二叉树我是真的不会,我还是看了何钦铭老师的小白专场讲解才做出来的。这一题有很多细节,但是主要操作只有两个,第一个是建立二叉树;第二个是判断两颗树是否同构。
因为题目给出的结点都是以编号的方式给出的,所以我们可以用结构数组来储存二叉树。
1 2 3 4 5
| typedef struct Tree{ char data; int left; int right; }Tree;
|
读取数据的时候有些结点的孩子坐标为‘-’,所以我们用char类型来读取,判断是‘-’,就转换成数字49(不要问我为什么用49而不用-1,因为‘-’的ASCII码值为49,我一开始想直接用int读取‘-’,代码都是用49来判断结点是否为空,结果出错了),不是‘-’,就转换为本来的数字。
难点是怎么判断两棵树是否同构,我一开始知道要用递归的写法来判断,但是我的思路错了。我一开始想的是先判断A树B树的头节点,然后判断他们的左右孩子是否相等。如果不相等,就交换一次在判断相不相等;若交换后相等则继续判断他们的左右孩子的左右孩子是否相等,若交换后不相等则退出。但是这种想法很难实现会漏掉很多情况。
后面就看了老师的思路,用了老师的方法。
具体代码如下
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include<stdio.h> typedef struct Tree{ char data; int left; int right; }Tree; int isomorphism; int is_isomorphism(Tree* A,int t1,Tree* B,int t2){ if(t1==49&&t2==49){ return 1; } if(t1==49&&t2!=49||t1!=49&&t2==49){ return 0; } if(A[t1].data!=B[t2].data){ return 0; } if(A[t1].left==49&&B[t2].left==49){ return is_isomorphism(A,A[t1].right,B,B[t2].right); } if((A[t1].left!=49&&B[t2].left!=49)&&(A[A[t1].left].data==B[B[t2].left].data)){ return (is_isomorphism(A,A[t1].left,B,B[t2].left)&&is_isomorphism(A,A[t1].right,B,B[t2].right)); } else{ return (is_isomorphism(A,A[t1].left,B,B[t2].right)&&is_isomorphism(A,A[t1].right,B,B[t2].left)); } } int main(){ int n1,n2,left,right,first_head=49,second_head=49; char data='-'; char save[3]; scanf("%d",&n1); Tree first_tree[11]; int first[11]={0}; if(n1!=0){ for(int i=0;i<n1;i++){ scanf("\n%c %c %c",&first_tree[i].data,&save[0],&save[1]); if(save[0]==data) first_tree[i].left = 49; else first_tree[i].left = save[0] - '0'; if(save[1]==data) first_tree[i].right = 49; else first_tree[i].right = save[1] - '0'; if(first_tree[i].left!=49) first[first_tree[i].left] = 1; if(first_tree[i].right!=49) first[first_tree[i].right] = 1; } } scanf("%d",&n2); Tree second_tree[11]; int second[11]={0}; if(n2!=0){ for(int i=0;i<n2;i++){ scanf("\n%c %c %c",&second_tree[i].data,&save[0],&save[1]); if(save[0]==data) second_tree[i].left = 49; else second_tree[i].left = save[0] - '0'; if(save[1]==data) second_tree[i].right = 49; else second_tree[i].right = save[1] - '0'; if(second_tree[i].left!=49) second[second_tree[i].left] = 1; if(second_tree[i].right!=49) second[second_tree[i].right] = 1; } }
for(int i=0;i<n1;i++){ if(!first[i]) first_head = i; } for(int i=0;i<n2;i++){ if(!second[i]) second_head = i; } isomorphism = is_isomorphism(first_tree,first_head,second_tree,second_head); if(isomorphism||(n1==0&&n2==0)) printf("Yes\n"); else printf("No\n"); return 0; }
|