题目内容

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

图一

图二

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

输入格式

输入给出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 -

输出样例

Yes

题目分析

存储问题

首先要解决的是数据的存储问题

1.存储在什么样的数据结构中。

2.如何从给定的输入格式把数据存储进该结构中。

根据题目的条件该二叉树的结点不超过10个,数据量并不大且上限确定,很容易联想到使用结构体数组,即静态链表。

静态链表在物理结构上是一维数组,但其思想与作用与链表相同,用数组下标代替指针指向对应数据位置。这也说明了链表或者说是链式存储是一种物理结构而非逻辑结构。

因此我们可以构造一个结构体。

typedef int treenode;
struct node{
char data;
treenode left;
treenode right;
}T1[MAXSIZE],T2[MAXSIZE];

用整形变量作为数组下标来指向对应位置来代替指针。

关于如何把数据存储进结构中,由于左右子树用'-'和数字一起来表示,所以我使用%c读取左右子树信息后存储在另外变量中并进行了判断,如果是'-'则为Null,否则为对应的数组下标。

根节点问题

由于数组中的节点数据是无序的,所以我们用一个构造一个和结构体数组等长的check数组(与每个结点一一对应)来检查数据是否为任意结点的儿子结点,如果不是则为根节点。

判断方法为每读取一个结点的左右子树,只要不为空,就在对应的check数组中标记。

是否同构问题

在二叉树相关问题中,递归总是被反复提及和使用,因此本问题也可以用递归的方法来解决。

关于一颗二叉树是否同构,我们首先从二叉树的五种基本形态入手:

二叉树的基本形态有:

a)空树;

b)只有根的树,即单结点;

c)有根且有一个左子树;

d)有根且有一个右子树;

e)有根且有一个左子树,有一个右子树。

与下图一一对应

这个知识点看似没有什么用,毕竟一看就知道是那么回事,但是如果加以理解并运用就能很简单的理清思路。

对于两棵二叉树A和B最简单最基本的形态是空树,那么如果两个二叉树都为空树那么必定同构,如果一个不空一个空的话必定不同构。

如果不为空树的话,则看第二种复杂一点的形态,即只有一个根结点的二叉树,如果这两个二叉树的根节点不一致,那么必定不同构。如果一致那么同构(一致同构可以省略因为这种情况包含在下面的情况中)

如果这两颗二叉树更加复杂,有一个子树不为空,那么这时有四种情况。

1.两棵二叉树都是左子树为空,则递归判断两棵二叉树的右子树是否为空。

2.两棵二叉树都是右子树为空,则递归判断两棵二叉树的左子树是否为空。

3.二叉树A左子树为空,二叉树B右子树为空,则递归判断二叉树A的右子树与二叉树B的左子树是否同构。

4.二叉树A右子树为空,二叉树B左子树为空,则递归判断二叉树A的左子树与二叉树B的右子树是否同构。

最复杂的情况,二叉树的左右子树都不为空,首先观察二叉树A和B的左子树元素的数据是否相同,

1.如果相同,则说明这两棵二叉树如果同构的话,必定满足二叉树A左子树与二叉树B左子树同构且二叉树A右子树与二叉树B右子树同构。

2.如果不同,则必须满足二叉树A左子树与二叉树B右子树同构且二叉树A右子树与二叉树B左子树同构才能使整棵二叉树同构。

具体代码如下:

bool isomorphism(treenode root1, treenode root2)
{
if (root1 == Null && root2 == Null)//两棵二叉树都为空树
return true;
if ((root1 != Null && root2 == Null) || (root1 != Null && root2 == Null))//一棵二叉树为空,一棵不为空
return false;
if (T1[root1].data != T2[root2].data)//两棵二叉树根节点数据不同时
return false;
if (T1[root1].left == Null && T2[root2].left == Null)
return isomorphism(T1[root1].right, T2[root2].right);
if(T1[root1].right==Null&&T2[root2].right==Null)
return isomorphism(T1[root1].left, T2[root2].left);
if(T1[root1].left==Null&&T2[root2].right==Null)
return isomorphism(T1[root1].right, T2[root2].left);
if (T1[root1].right == Null && T2[root2].left == Null)
return isomorphism(T1[root1].left, T2[root2].right);//共四种两棵二叉树都有一棵子树为空的情况
if (T1[T1[root1].left].data == T2[T2[root2].left].data)
return (isomorphism(T1[root1].left, T2[root2].left) && isomorphism(T1[root1].right, T2[root2].right));
else
return (isomorphism(T1[root1].left, T2[root2].right) && isomorphism(T1[root1].right, T2[root2].left));//共两种两棵二叉树的左右子树都不为空的情况。
}

完整代码

#include
#include
#define MAXSIZE 10
#define Null -1
typedef int treenode;
struct node{
char data;
treenode left;
treenode right;
}T1[MAXSIZE],T2[MAXSIZE];

treenode createtree(node *tree);
bool isomorphism(treenode root1, treenode root2);

int main(void)
{
int root1, root2;
root1 = createtree(T1);
root2 = createtree(T2);
if (isomorphism(root1, root2))
printf("Yes\n");
else
printf("No\n");
}

treenode createtree(struct node *tree)
{
treenode root = Null;
int check[MAXSIZE] = { 0 };
int size;
char tl, tr;
scanf("%d", &size);
if (size)
{
for (int i = 0; i

提交结果

【PTA】浙江大学数据结构慕课 课后编程作业 03-树1 树的同构的更多相关文章

  1. java数据结构和算法编程作业系列篇-数组

    /** * 编程作业 2.1 向highArray.java程序(清单2.3)的HighArray类添加一个名为getMax()的方法,它返回 数组中最大关键字的值,当数组为空时返回-1.向main( ...

  2. deeplearning.ai 旁听如何做课后编程作业

    在上吴恩达老师的深度学习课程,在coursera上. 我觉得课程绝对值的49刀,但是确实没有额外的钱来上课.而且课程提供了旁听和助学金. 之前在coursera上算法和机器学习都是直接旁听的,这些课旁 ...

  3. 【吴恩达课后编程作业】第二周作业 - Logistic回归-识别猫的图片

    1.问题描述 有209张图片作为训练集,50张图片作为测试集,图片中有的是猫的图片,有的不是.每张图片的像素大小为64*64 吴恩达并没有把原始的图片提供给我们 而是把这两个图片集转换成两个.h5文件 ...

  4. | C语言I作业03

    | C语言I作业03 标签: 18软件 李煦亮 问题 答案 这个作业属于那个课程 C语言程序设计I 这个作业要求在哪里 https://edu.cnblogs.com 我在这个课程的目标是 学会和掌握 ...

  5. Stanford coursera Andrew Ng 机器学习课程编程作业(Exercise 2)及总结

    Exercise 1:Linear Regression---实现一个线性回归 关于如何实现一个线性回归,请参考:http://www.cnblogs.com/hapjin/p/6079012.htm ...

  6. UI-12组结对编程作业总结

    UI-12组结对编程作业总结 源码Github地址 https://github.com/tilmto/TILMTO/tree/master/Arithmetic 作业摘要 本次结对编程作业分为以下两 ...

  7. # 2017-2018-20172309 暑期编程作业:APP

    2017-2018-20172309 暑期编程作业:基于有道词典API的翻译软件的实现. 写在前面:这个博客可以说是拖了很久了.因为做这个APP已经很久了,很多东西都已经忘记了,所以一直都懒得写.但是 ...

  8. ufldl学习笔记与编程作业:Softmax Regression(vectorization加速)

    ufldl学习笔记与编程作业:Softmax Regression(vectorization加速) ufldl出了新教程,感觉比之前的好.从基础讲起.系统清晰,又有编程实践. 在deep learn ...

  9. C语言I—2019秋作业03

    这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 C语言I-2019秋作业03 我在这个课程的目标是 掌握if-else语句,运算关系 这个作业在那个具体方面帮助我实现目标 row 2 c ...

随机推荐

  1. Ubuntu Server : 自动更新

    Ubuntu(16.04/18.04) 默认会每天自动安装系统的安全更新,但是不会自动安装包的更新.本文梳理 Ubuntu 16.04/18.04 系统的自动更新机制,并介绍如何配置系统自动更新所有的 ...

  2. 多线程之NSThread

    关于多线程会有一系列如下:多线程之概念解析 多线程之pthread, NSThread, NSOperation, GCD 多线程之NSThread 多线程之NSOperation 多线程之GCD一, ...

  3. scrapy学习(完全版)

    scrapy1.6中文文档 scrapy1.6中文文档 scrapy中文文档 Scrapy框架 下载页面 解析页面 并发 深度 安装 scrapy学习教程 如果安装了anconda,可以在anacon ...

  4. Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)

    Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...

  5. CentOS重置MySQL root密码的方法

    1.修改MySQL的登录设置: # vim /etc/my.cnf 在[mysqld]的段中加上一句:skip-grant-tables 例如: [mysqld] skip-grant-tables  ...

  6. java web基础 js、JSP、servlet之间的传递

    @ JS 与 JSP :JSP无法直接获取JS的值,只能通过隐藏表单或者dom节点设置. JSP中设置隐藏表单input,或者设置任意一个隐藏或者不隐藏的节点比如div, 而JS就通过document ...

  7. python request接口测试笔记(1)

    python request接口测试笔记(1) 涉及到的功能说明: 需要登录拿到token,才能进行下一个接口的请求 读取csv文件中的信息,作为接口的参数 将接口响应结果,写入csv文件,以便分析统 ...

  8. (数据科学学习手札67)使用Git管理Github仓库

    一.简介 Git是目前使用最广泛的分布式版本控制系统,通过Git可以方便高效地管理掌握工作过程中项目内容文件的更新变化情况,通过Git我们可以以命令行的形式完成对Github上开源仓库的clone,以 ...

  9. .netcore 分布式事务CAP2.6之控制台使用

    上一编讲了cap2.6的快速入门,这次我们来讲讲在控制台中如何使用cap2.6.因为cap2.6的内存模式目前已经可以使用了,相关组件已经更新,所以这次我们以简单的内存模式为例. 1:创建项目 创建一 ...

  10. urllib爬虫模块

    网络爬虫也称为网络蜘蛛.网络机器人,抓取网络的数据.其实就是用Python程序模仿人点击浏览器并访问网站,而且模仿的越逼真越好.一般爬取数据的目的主要是用来做数据分析,或者公司项目做数据测试,公司业务 ...