树的同构

最近为了准备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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值