题目信息
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。
现给定两棵树,请你判断它们是否是同构的。
输入
给出 2棵二叉树的信息。对于每棵树,第一行中给出一个非负整数N (≤20)
,即该树的结点数(此时假设结点从0到N−1编号);随后N行,第 i 行对应编号第 i 个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出 “-”。给出的数据间用一个空格分隔。注意:树的根为结点“A",并保证树中每个结点存储的字母是不同的。
输出
如果两棵树是同构的,输出“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 -
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
No.
测试样例3
1
A - -
1
A - -
Yes.
解答
#include <iostream>
using namespace std;
struct BTreeNode
{
char data;
int Left;
int Right;
} T1[25], T2[25];
int Create(BTreeNode *T)
{//返回根的位置
int N;
cin >> N;
int RootFind[25] = {0};//没有被指到过的就是根
for (int i = 0; i < N; i++)
{
char tmpLeft, tmpRight;
cin >> T[i].data >> tmpLeft >> tmpRight;
if (tmpLeft == '-')
{
T[i].Left = -1;
}
else
{
T[i].Left = tmpLeft-'0';
RootFind[T[i].Left]++;
}
if (tmpRight == '-')
{
T[i].Right = -1;
}
else
{
T[i].Right = tmpRight-'0';
RootFind[T[i].Right]++;
}
}
for (int i = 0; i < N; i++)
{
if (RootFind[i] == 0)
{
return i;
}
}
}
int Isomorphism(int x, int y)
{
if (x == -1 && y == -1)
{//如果两个都恰好是空节点则其实是相同的
return 1;
}
else if ((x != -1 && y == -1) || (x == -1 && y != -1))
{//两边一个有子节点,一个没有子节点
return 0;
}
else if (T1[x].data != T2[y].data)
{//两个位置的数值不相等,则判定为直接为不一样的
return 0;
}
else if (Isomorphism(T1[x].Left, T2[y].Left) && Isomorphism(T1[x].Right, T2[y].Right))
{//如果左边的等于左边的且右边的等于右边的
return 1;
}
else if (Isomorphism(T1[x].Left, T2[y].Right) && Isomorphism(T1[x].Left, T2[y].Right))
{//左边的等于右边的,右边的等于左边的
return 1;
}
else
{
return 0;
}
}
int main()
{
//freopen("/Users/zhj/Downloads/test.txt", "r", stdin);
int RootIndex1 = Create(T1);
int RootIndex2 = Create(T2);
if (Isomorphism(RootIndex1, RootIndex2))
{
cout << "Yes." << endl;
}
else
{
cout << "No." << endl;
}
return 0;
}