您的位置:首页 > 编程语言 > C语言/C++

7-3 树的同构(25 分)

2017-12-18 21:40 176 查看
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。

//示例图略

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

输入格式:>

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N

(≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:>

如果两棵树是同构的,输出“Yes”,否则输出“No”。

输入样例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:

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

根据输入格式,可以想到树的建立可以使用一个结构体数组表示。再由树的特征,因为题意要判断树是否相同,是通过某两个内容一致的节点的特征是否一致来判断的,这里就不一定需要知道用数组表示的树的树根在哪里。

#include<stdio.h>
#include<stdlib.h>

typedef struct Tree *BT;
struct Tree
{
int left;
int right;
char data;
};

BT writeTree(int);
int isLikeTree(BT, int, BT, int);

int main(void)
{
int N, M;
BT T1, T2;

scanf("%d", &N);
getchar();
T1 = writeTree(N);

scanf("%d", &M);
getchar();
T2 = writeTree(M);

if(isLikeTree(T1, N, T2, M) == 0)
puts("Yes");
else
puts("No");

free(T1);
free(T2);

return 0;
}

//建树并输入树的信息,输入按字符
BT writeTree(int n)
{
int count;
char cl, cr;
BT BitTree;

BitTree = (BT)calloc(n, sizeof(struct Tree));

for(count = 0; count < n; count++)
{
BitTree[count].data = getchar();
getchar();
cl = getchar();
getchar();
cr = getchar();
getchar();

if(cl >= '0' && cl <= '9')
{
BitTree[count].left = cl - '0';
}
else
{
BitTree[count].left = -1;
}

if(cr >= '0' && cr <= '9')
{
BitTree[count].right = cr - '0';
}
else
{
BitTree[count].right = -1;
}
}

return BitTree;
}

/*传入树1根、树1节点数,树2根、树2节点数。
是同一棵树时返回0*/
int isLikeTree(BT Tree1, int N, BT Tree2, int M)
{
int cnt1, cnt2;
int JUG = 0;

if(N != M)
return 1;

if(N == 1 && M == 1 )
{
if(Tree1[cnt1].data - Tree2[cnt2].data)
return 1;
}
//搜索两树的每一个节点
for(cnt1 = 0; cnt1 < N; cnt1++)
{
for(cnt2 = 0; cnt2 < M; cnt2++)
{
if(Tree1[cnt1].data - Tree2[cnt2].data == 0) //比较节点值相同的节点
{
if(Tree1[cnt1].left == -1 && Tree2[cnt2].left == -1
&& Tree1[cnt1].right == -1 && Tree2[cnt2].right == -1) //遇到同为叶节点
{
break;
}

else if( (Tree1[cnt1].left == -1 && Tree1[cnt1].right == -1)
&& (Tree2[cnt2].right != Tree2[cnt2].left) ) //树1叶节点,对应到树2有子节点
{
JUG++;
break;
}

else if( (Tree1[cnt1].left != Tree1[cnt1].right)
&& (Tree2[cnt2].right == -1 && Tree2[cnt2].left == -1) ) //树1节点有子节点,对应树2叶节点
{
JUG++;
break;
}

else if( (Tree1[cnt1].left == -1 || Tree1[cnt1].right == -1)
&& (Tree2[cnt2].right != -1 && Tree2[cnt2].left != -1) ) //树1单边子,树2叶节点
{

4000
JUG++;
break;
}

else if( (Tree2[cnt2].left == -1 || Tree2[cnt2].right == -1)
&& (Tree1[cnt1].right != -1 && Tree1[cnt1].left != -1) ) //树2单边子,树1叶节点
{
JUG++;
break;
}

else
{
if( ( (Tree1[Tree1[cnt1].left].data != Tree2[Tree2[cnt2].left].data)
&& (Tree1[Tree1[cnt1].right].data != Tree2[Tree2[cnt2].right].data) )
&&
( (Tree1[Tree1[cnt1].right].data != Tree2[Tree2[cnt2].left].data)
&& (Tree1[Tree1[cnt1].left].data != Tree2[Tree2[cnt2].right].data) ) ) //两树节点的子节点都对不上
{
JUG++;
}

break;
}
}//if(Tree1[cnt1].data - Tree2[cnt2].data == 0)
}//for(cnt2 = 0; cnt2 < M; cnt2++)
}//for(cnt1 = 0; cnt1 < N; cnt1++)

return JUG;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息