FDS编程作业记录 · 其三 · 树的同构

题目

题干

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):

题目分析

阅读题干我们不难看出,所谓的同构(即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的测试结果:

不出意外应该是正确的。

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值