第五章学习小结

---恢复内容开始---

第五章主要学习的是树与二叉树,有利用数组进行存储的顺序二叉树,也有利用链表进行存储的链式二叉树,在这个基础上又展开了二叉树的遍历。

二叉树的遍历分为前序遍历,中序遍历以及后序遍历,主要区别在于遍历的顺序不同。

前序遍历:

(1)访问根结点。

(2)前序遍历左子树

(3)前序遍历右子树 。

中序遍历:

(1)中序遍历左子树

(2)访问根结点

(3)中序遍历右子树

后序遍历:

1)后序遍历左子树

(2)后序遍历右子树

(3)访问根结点


对于二叉树树的遍历的应用:

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

图1

图2

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

输入格式:

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

输出格式:

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

输入样例1(对应图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(对应图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 <iostream>
using namespace std;

typedef struct TreeNode //定义一个树的结构
{
	char data; //结点的数据
	char parent; //结点的双亲
}TreeNode;

bool input_output() //boll类型函数判断二叉树是否同构
{
	int i,j; //定义参数 

	TreeNode tree1[10],tree2[10]; //定义两个数的结构 

	char ltree,rtree; //定义两个字符参数 

	int n; //定义结点数参数
	cin>>n; //输入第一棵树的结点数 

	for(i=0;i<n;i++)
	{
		tree1[i].parent=‘0‘; //将第一棵树的所有结点的parent赋值为‘0‘
	}

	for(i=0;i<n;i++)
	{
		cin>>tree1[i].data; //输入结点数据
		cin>>ltree>>rtree; //输入结点对应的左右子结点 

		if(ltree!=‘-‘) //若子结点不为空
		{
			j=ltree-48; //字符类型转换为int型,得到结点对应下标
			tree1[j].parent = tree1[i].data ; //将结点的data值赋给子结点的parent
		}

		if(rtree!=‘-‘) //若子结点不为空
		{
			j=rtree-48; //字符类型转换为int型,得到结点对应下标
			tree1[j].parent = tree1[i].data; //将结点的data值赋给子结点的parent
		}
	}

	int m; //定义结点数参数
	cin>>m; //输入第二棵树的结点数

	for(i=0;i<m;i++)
	{
		tree2[i].parent=‘0‘; //将第二棵树的所有结点的parent赋值为‘0‘
	}

	for(i=0;i<m;i++)
	{
		cin>>tree2[i].data; //输入结点数据
		cin>>ltree>>rtree; //输入结点对应的左右子结点 

		if(ltree!=‘-‘) //若子结点不为空
		{
			j=ltree-48; //字符类型转换为int型,得到结点对应下标
			tree2[j].parent = tree2[i].data; //将结点的data值赋给子结点的parent
		}

		if(rtree!=‘-‘) //若子结点不为空
		{
			j=rtree-48; //字符类型转换为int型,得到结点对应下标
			tree2[j].parent = tree2[i].data; //将结点的data值赋给子结点的parent
		}
	}

	if(m!=n)return false; //若结点数不同,返回flase 

	if(m==1&&n==1&&tree1[0].data==tree2[0].data)return true; //结点数都为1,直接比较数据值,若为真则返回true
	else if(m==1&&n==1&&tree1[0].data!=tree2[0].data)return false; //若为假则返回false 

	for(i=0;i<n;i++)
	{
		for(j=0;j<m;j++)
		{
			if(tree1[i].data==tree2[j].data) //若两棵树的某一结点数据值相同,则比较其双亲
			{
				if(tree1[i].parent!=tree2[j].parent) //若双亲不同,则返回false
				{
					return false;
				}
			}
		}
	}

	return true; //双亲相同,返回true
}

int main()
{
	bool a = input_output(); //定义bool型参数 

	if(a)cout<<"Yes"; //两棵树同构,输出“Yes”
	else cout<<"No"; //两棵树不同构,输出“No” 

	return 0;
}

  

原文地址:https://www.cnblogs.com/xiedehan/p/10805658.html

时间: 2024-07-28 22:20:24

第五章学习小结的相关文章

第三章学习小结—-转

[学习目标] 01掌握一维数组的声明和使用方法(OK) 02掌握二维数组的声明和使用方法(OK) 03掌握字符串的声明.赋值.比较和连接方法(连接很少用) 04熟悉字符的ASCII码和ctype.h中的字符函数 05正确认识++.+=等能修改变量的运算符(OK) 06学会用编译选项-Wall获得更多的警告信息(OK) 07了解不同操作系统中换行符的表示方法(嗯) 08掌握fgetc和getchar的使用方法(fgetc基本没用过) 09掌握预处理和迭代开发的技巧(嗯) 程序3-1 逆序输出 输入

数据结构 第一章学习小结

数据结构   第一章学习小结 1.数据结构第1章的心得体会: 这周学习了数据结构的绪论及第一章.初步了解了数据结构与算法的相关概念,一开始看书看视频时觉得还挺抽象的,不能够完全理解.但是反复多看了几遍之后,结合例题,自己去操作去跑代码,慢慢觉得容易理解接受起来了.由于现在以网课形式进行教学,老师上课的同时基本还是靠自己去理解学习.当然老师也发挥很大的作用,比如让我们更深入的了解递归的空间复杂度为什么与问题规模有关,又怎样去找到该函数的临界值等等.既锻炼了我们深入思考的能力,也让我们更加清楚了解不

第5章学习小结

第五章主要学习了树的知识,以前一直很好奇,为什么电脑能存储像树一样的数据结构,学完才发现,ADT加数组或者ADT加链表真的可以衍生出多种多样的数据类型,以下做出本章小结: 1.利用ASCII码实现不同类型的数据的转换,如:int = char - ‘0’. 2.学会了利用bool类型标记找出所需数据类型,如找根节点,先将bool型数组初始化成false,输入过的节点标记为true,那么为false的即为根节点. 3.树的四种遍历方式:利用递归实现三种遍历方式 先序: void PreOrderT

安卓权威编程指南 - 第五章学习笔记(两个Activity)

学习安卓编程权威指南第五章的时候自己写了个简单的Demo来加深理解两个Activity互相传递数据的问题,然后将自己的学习笔记贴上来,如有错误还请指正. IntentActivityDemo学习笔记 题目:ActivityA登录界面(用户名.密码.登陆按钮),ActivityB(Edit,返回按键:SubmitButton).A界面输入用户名和密码传到B中,B验证用户输入的用户名和密码,如果错误就返回A,并用Toast 显示用户名和密码错误:如果正确,就在第二个 activity中显示一个Edi

构建之法第五章学习

今天我学习了<构建之法>第五章 团队和流程.首先我了解了写了再改模式(Code-and-Fix) 史蒂夫·迈克康奈尔(Steve McConnell)在这里提到了不少开发流程.第一个提到的开发流程.这个流程也有好处,不需要太多其他准备或相关知识,大家上来就写代码,也许就能写出来,写不出来就改,也许能改好.当面临下面的任务时,也许这个方法是有用的.但是,要写一个有实际用户.解决实际需求的软件,这个方法的缺点就太大了. 然后我学习了瀑布模型 当软件行业还在年幼的时期,它从别的成熟行业(硬件设计,建

《构建之法》第三、四、五章学习总结

第三章讲的是关于如何成为一名合格甚至优秀的软件工程师.第一节主要讲的是个人能力的发展与团队合作的关系:第二节讲的则是关于软件工程师的职业发展:最后一节通过用魔方举例向我们讲述了怎样提升自己的技能. 第四章讲的是关于软件开发时两个人该怎样合作.这一章的前三节讲的都是关于代码规范,包括风格规范和设计规范:第四节讲的是关于代码复审时的问题,代码复审的正确定义是看代码是否在"代码规范"的框架内正确地解决了问题:第五节讲的是结对编程 :第六节介绍了两人合作的不同阶段和需要了解的相关技巧. 第五章

第五章内容小结

在第五章,我们学习了树这个数据结构,并且学习了其定义.遍历等操作,最后还学习了哈夫曼树. 一.树的遍历 树的遍历操作有以下三种: 1.先序遍历(根,左孩子,右孩子) void PreOrderTravel(node t[], int x) { cout << t[x].name << " "; if(t[x].lch!=-1) PreOrderTravel(t, t[x].lch); if(t[x].rch!=-1) PreOrderTravel(t, t[x]

《Linux内核设计与实现》第五章学习笔记

第五章 系统调用 操作系统中,内核提供了用户进程与内核进行交互的一组接口.这些接口让应用程序受限的访问硬件设备,提供了新进程与已有进程进行通信的机制,也提供了申请操作系统其他资源的能力.提供接口主要是为了保证系统稳定可靠,避免应用程序恣意妄行. 课堂知识点回顾 1. 系统调用:需要int 0x80模拟中断让硬件触发.同步.主动地进入系统空间. 2. 硬中断:异步.被动地进入系统空间.CPU运行时发生错误则中断,中断后没有进程调度. 3. 软中断:中断后还执行其他进程调度. 4. 系统调用过程:

Thinking In Java第五章学习笔记

第五章:初始化与清理 初始化和清理是涉及程序安全的两个问题.Java构造器用于新建对象时的初始化,而垃圾回收器则进行清理. 构造器的名称必须与类名一样,虽然构造器是一种特殊的方法,但是每个方法首字母小写的编码风格并不适合用于构造器. 构造器是没有返回值的,但是new表达式却返回了对新建对象的引用. 方法重载是构造器所必须的.每个重载方法都必须独一无二的参数列表.甚至参数顺序的不同,也足以区分两个方法.不过一般不建议这么做,因为这会使代码难以维护.当传入的数据类型小于方法中声明的形式参数类型,实际