树的同构
程序员文章站
2022-06-07 21:46:38
...
最近为了准备PAT考试,重新复习了数据结构,把数据结构的题发上来,以便于自己日后复习
和树有关的操作一般都可以通过递归来很清晰地实现,递归中注意跳出递归的条件(就是两个节点为空的情况)
1.当甲与乙中至少有一个空树的时候,则甲与乙必须同时为空树,否则就不可能为同构
2.甲与乙不为空时,但是数据不同也不同构
3.最重要的就是要判断甲的左跟乙的右&&甲的右与乙左是否相等,相等说明左右子树有交换为同构,或者是甲的左跟乙的左
&&甲的右跟乙的右是否相等,若相等则说明甲与乙的儿子节点位置完全相同,为同构
#include<stdio.h>
#pragma warning(disable:4996)
#define MaxTree 10
#define Null -1 //将Null定义为-1而不能是0,因为数组下标为0的地方仍保存有节点
typedef char ElementType;
typedef int Tree;
struct TreeNode { //定义二叉树节点
ElementType Data;
Tree Left;
Tree Right;
}T1[MaxTree], T2[MaxTree];
int N, check[MaxTree]; //check数组用于寻找树的根节点
Tree BuildTree(struct TreeNode T[]) {
int Root = Null, i; //刚开始将节点置为空,若为空树的时候可返回Null
char cl, cr;
scanf("%d", &N);
if (N) { //如果不为空树的话
for (i = 0; i<N; i++) check[i] = 0; //将check数组置为0
for (i = 0; i<N; i++) {
scanf("\n%c %c %c", &T[i].Data, &cl, &cr); //把换行符放在前面吃掉前面scanf后的回车,而最后一个scanf不能有回车,一举两得
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;//没有被check的节点为头结点
Root = i;
}
return Root;
}
int Isomorphic(Tree R1, Tree R2) {
if ((R1 == Null)||(R2 == Null)) //如果为空树则是同构的
return R1==R2;
if ((T1[R1].Data) != (T2[R2].Data))//如果数据不同则不是同构的
return 0;
return( Isomorphic(T1[R1].Left, T2[R2].Left) && Isomorphic(T1[R1].Right, T2[R2].Right))||( Isomorphic(T1[R1].Left, T2[R2].Right) && Isomorphic(T1[R1].Right, T2[R2].Left));
//判断左子树的左儿子与右子树的右儿子,左子树的右儿子与右子树的左儿子是否相同----这种情况是两个子树的儿子节点有交换
//判断左子树的左儿子与右子树的左儿子,左子树的右儿子与右子树的右儿子是否相同----这种情况是两个子树的儿子节点没有交换
}
int main() {
Tree R1, R2; //首先建立两棵树,R1,R2为树的根节点
R1 = BuildTree(T1);
R2 = BuildTree(T2);
if (Isomorphic(R1, R2)) //Isomorphic函数判断是否同构
printf("Yes\n");
else printf("No\n");
return 0;
}