PTA 03-树1 树的同构 (25分)

题目地址

https://pta.patest.cn/pta/test/15/exam/4/question/711

 

5-3 树的同构   (25分)

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

 


 

图1

图2

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

 

输入格式:

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数NN (\le 1010),即该树的结点数(此时假设结点从0到N-1N1编号);随后NN行,第ii行对应编号第ii个结点,给出该结点中存储的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


/*
评测结果
时间	结果	得分	题目	编译器	用时(ms)	内存(MB)	用户
2017-07-08 15:57	答案正确	25	5-3	gcc	14	1	
测试点结果
测试点	结果	得分/满分	用时(ms)	内存(MB)
测试点1	答案正确	7/7	14	1
测试点2	答案正确	7/7	2	1
测试点3	答案正确	3/3	2	1
测试点4	答案正确	2/2	1	1
测试点5	答案正确	3/3	2	1
测试点6	答案正确	3/3	10	1
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 10

/*
思路
跟视频教程中的从根向下遍历来判断同构不同,本算法从叶子节点向上搜索。
因为树是静态建立的,所以父节点比较容易记录。 
*/
struct treenode{//创建节点结构体 
	int data;	//存放内容 
	int father; //存放父节点位置 
	int lc;		//左儿子 
	int rc;		//右儿子 
	int isleaf; //是否为叶节点 
};

typedef struct tree{//树结构体 
	struct treenode nodes[MAXLEN];//节点单元 
	int len;//节点数量 
	int root;//根节点位置 
}* ptrTree;

ptrTree CreateTree()//建树 
{	
	int i;
	ptrTree T;
	T=(ptrTree)malloc(sizeof(struct tree));
	for(i=0;i<MAXLEN;i++)
		T->nodes[i].father=-1; //提前将每个节点的父节点都初始化为-1 
	return T;
}

void DestoryTree(ptrTree T) //释放空间 
{
	free(T);
}

void input(ptrTree T) //读入树 
{
	int i,length;
	scanf("%d",&length);
//	printf("%d,line40\n",length);//test
	T->len=length;
	getchar();//skip a space
	for(i=0;i<length;i++)
	{
	T->nodes[i].data=getchar();
		getchar();//skip a space
	T->nodes[i].lc=getchar();
		getchar();//skip a space
	T->nodes[i].rc=getchar();
		getchar();//skip a space
		
	T->nodes[i].lc-='0';
	T->nodes[i].rc-='0';

//	printf("line58\n");//test
//	printf("#%d data=%c L=%d R=%d Father=%d leaf=%d\n",i,T->nodes[i].data,T->nodes[i].lc,T->nodes[i].rc,T->nodes[i].father,T->nodes[i].isleaf);//test 

	if(T->nodes[i].lc>=0)//如果一个节点有孩子,将此节点标记为孩子的父节点 
		T->nodes[T->nodes[i].lc].father=i;
	if(T->nodes[i].rc>=0)
		T->nodes[T->nodes[i].rc].father=i;
	if(T->nodes[i].lc<0 && T->nodes[i].rc<0)//如果一个节点没有孩子,那么此节点为叶节点 
		T->nodes[i].isleaf=1;
		
//		printf("#%d data=%c L=%d R=%d Father=%d leaf=%d\n",i,T->nodes[i].data,T->nodes[i].lc,T->nodes[i].rc,T->nodes[i].father,T->nodes[i].isleaf);//test 
	}

	for(i=0;i<length;i++){//遍历整棵树,父节点为-1的节点即为根。不过次算法后来也没用上这个量,留着不删了。 
		if(T->nodes[i].father<0){
			T->root=i;
			break;
		}
	}
}
void printTree(ptrTree T)//测试用函数,输出树,看是否正确 
{
	int i;
	printf("Tree.len=%d root=%d\n ",T->len,T->root);
	for(i=0;i<T->len;i++){
		printf("#%d %c L=%d R=%d Father=%d leaf=%d\n",i,T->nodes[i].data,T->nodes[i].lc,T->nodes[i].rc,T->nodes[i].father,T->nodes[i].isleaf);
	}
}

int CheckPath(ptrTree T1,ptrTree T2,int idx,int otheridx)//测试以下标idx的节点为起点,搜索另一棵树上的data相同的节点,若这二者的父节点值也相同,那么递归搜索到根为止。如不相同,则返回0; 
{
	int i,t1f,t2f;
	t1f=T1->nodes[idx].father;
	if(otheridx<0){//T2对应的下标值如果已知,那么不用再搜一遍了 
		for(i=0;i<T1->len;i++)
		if(T1->nodes[idx].data==T2->nodes[i].data)
			break;
		t2f=T2->nodes[i].father;
	}else
		t2f=T2->nodes[otheridx].father;
	
	if(( t1f<0 && t2f>=0) || (t1f>=0 && t2f<0)) return 0;
	if (T1->nodes[t1f].data==T2->nodes[t2f].data){
		if(T1->nodes[t1f].father<0)
			return 1;
		else return CheckPath(T1,T2,t1f,t2f);
	}
	else return 0;
			
}
int Judge(ptrTree T1,ptrTree T2)
{
	int i,flag=1;
	if(T1->len!=T2->len)//两棵树若节点数不同直接跳出 
		return 0;
	
	if(T1->len==0){//两棵树都是空树,那么肯定算同构 
		return 1;
	}
	if(T1->len==1){//若两棵树都只有一个节点,那么比较节点的值是否相同即可 
		if(T1->nodes[0].data==T2->nodes[0].data)
			return 1;
		else return 0;
	}
	for(i=0;i<T1->len;i++){
		if(T1->nodes[i].isleaf==1)	{//搜寻所有的叶子节点,搜索向上的路径。如果两棵树所有叶子节点的向上路径都相同,那么这两棵树同构 
			flag=CheckPath(T1,T2,i,-1);//因为不知道第二棵树对应该叶子的index,所以填-1让它自己搜 
			if(flag==0) return 0;
		}
	}
	return 1;//循环期间没出过差错,那么可以return 1了 
}	
int main()
{
	int i;
	ptrTree T1,T2;
	T1=CreateTree();
	T2=CreateTree();
	input(T1);
	input(T2);
//	printTree(T1);//test 
//	printTree(T2);//test
	i=Judge(T1,T2);
	if(i==1) printf("Yes");
	else printf("No");
}

  

posted on 2017-07-09 09:17  gravitykey  阅读(869)  评论(0编辑  收藏  举报

导航