题目
题干
Two trees, T1
and T2
, are isomorphic if T1
can be transformed into T2
by swapping left and right children of (some of the) nodes in T1
. For instance, the two trees in Figure 1 are isomorphic because they are the same if the children of A, B, and G, but not the other nodes, are swapped. Give a polynomial time algorithm to decide if two trees are isomorphic.
Format of Functions
int Isomorphic( Tree T1, Tree T2 );
where Tree
is defined as the following:
typedef struct TreeNode *Tree;
struct TreeNode {
ElementType Element;
Tree Left;
Tree Right;
};
The function is supposed to return 1 if T1
and T2
are indeed isomorphic, or 0 if not.
Sample Program of Judge
#include <stdio.h>
#include <stdlib.h>
typedef char ElementType;
typedef struct TreeNode *Tree;
struct TreeNode {
ElementType Element;
Tree Left;
Tree Right;
};
Tree BuildTree(); /* details omitted */
int Isomorphic( Tree T1, Tree T2 );
int main()
{
Tree T1, T2;
T1 = BuildTree();
T2 = BuildTree();
printf(“%d\n”, Isomorphic(T1, T2));
return 0;
}
/* Your function will be put here */
Sample Output 1 (for the trees shown in Figure 1):
1
Sample Output 2 (for the trees shown in Figure 2):
0
题目分析
阅读题干我们不难看出,所谓的同构(即Isomorphic)需要保证两棵树在同层同一个parent有相同子树,但无所谓是左子树还是右子树。
传入了两棵树,我们需要逐层判断它们每层的结点值是否相同,用递归实现应当会简单一点。
解答
我的代码如下。在原答案基础上略微进行了改动,不保证完全正确。
int Isomorphic(Tree T1, Tree T2)
{
// 两棵树均为空,则同构
if (T1 == NULL && T2 == NULL)
return 1;
// 一棵树为空,另一棵非空,则不同构
if (T1 == NULL && T2 != NULL || T1 != NULL && T2 == NULL)
return 0;
// 两棵树均非空
if (T1->Element != T2->Element)
return 0;
// T1左子树为空,右子树非空
if (T1->Left == NULL && T1->Right != NULL) {
if (T2->Left == NULL)
return Isomorphic (T1->Right, T2->Right);
// 若T2左子树为空,则比较T1右子树和T2右子树
else if (T2->Right == NULL)
return Isomorphic (T1->Right, T2->Left);
// 若T2右子树为空,则比较T1右子树和T2左子树
else
return 0;
// 若T2左右子树非空,则两树不同构
}
// T1右子树为空,左子树非空
else if (T1->Left != NULL && T1->Right == NULL) {
if (T2->Left == NULL)
return Isomorphic (T1->Left, T2->Right);
else if (T2->Right == NULL)
return Isomorphic (T1->Left, T2->Left);
else
return 0;
} // 同理上个情况
// T1左右子树均为空
else if (T1->Left == NULL && T1->Right == NULL) {
if (T2->Left == NULL && T2->Right == NULL)
return 1;
// 若T2也是左右子树均为空则同构
else
return 0;
// 否则不同构
}
// T1左右子树均非空
else {
if (T1->Left->Element == T2->Left->Element)
return (Isomorphic (T1->Left, T2->Left) && Isomorphic (T1->Right, T2->Right));
// 若T1左子树与T2左子树结点值相等,则比较它们的左子树
else if (T1->Left->Element == T2->Right->Element)
return (Isomorphic (T1->Left, T2->Right) && Isomoorphic (T1->Right, T2->Left));
// 若T1左子树与T2右子树结点值相等,则比较T1的左子树和T2的右子树
else
return 0;
// 若T2左右子树没有一棵与T1左子树结点值相等,则不同构
}
}
题目中的建树函数被省略了,为了测试函数正确性我猜了一下,因为这个建树函数没有传参进去,所以输入过程略嫌麻烦,仅供参考:
Tree BuildTree () {
Tree theTree = (Tree)malloc(sizeof(struct TreeNode));
if (theTree == NULL) {
printf("Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
printf("Enter the element for the current node: ");
scanf(" %c", &theTree->Element);
char choice;
printf("Does the current node have a left child? (y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
theTree->Left = BuildTree();
} else {
theTree->Left = NULL;
}
printf("Does the current node have a right child? (y/n): ");
scanf(" %c", &choice);
if (choice == 'y' || choice == 'Y') {
theTree->Right = BuildTree();
} else {
theTree->Right = NULL;
}
return theTree;
}
以下为对Figure1的测试结果:
不出意外应该是正确的。