数据结构学习记录——判断是否为同一颗二叉搜索树(题意理解、求解思路、程序搭建框架、具体函数的实现)

news2024/12/28 2:06:16

目录

题意理解

问题

描述

输入样例 

输出样例

求解思路

建两棵二叉树

不建树

建一棵树

搜索树表示

程序框架搭建

如何建搜索树

如何判别

方法

查找函数

判断函数

其他函数


题意理解

给定一个插入序列就可以唯一确定一颗二叉搜索树。

但是,一颗给定的二叉搜索树却可以由多种不同的插入序列得到。

例如,按照序列{2,1,3}和{2,3,1}插入初始为空的二叉搜索树,都得到一样的结果。

问题

描述

对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入样例 

4 2              第一部分是两个整数:4表示插入二叉搜索树的节点数、2表示要进行比较的序列

3 1 4 2        第二部分是输入的序列                                                    

3 4 1 2        第三部分是后面输入的序列,它们全部都要与第二部分进行对比,判断是否一样

3 2 4 1

2 1

2 1

1 2

0

输出样例

Yes

No

No

 

求解思路

建两棵二叉树

根据两个序列分别建树,再去递归判别两棵树是否一样。

不建树

例如: 

3 1 2 4 对比 3 4 1 2,3都是根结点。

那找出所有比3大的结点和所有比3小的结点,发现:

很显然,我们能看出他们是同一棵二叉搜索树了。 

再来对比一组:3  1  2  4、3  2  4  1。

 

 这一组序列并不是同一棵二叉搜索树。

建一棵树

根据结点数来建立一棵二叉搜索树T,再来判别一个序列是否与二叉搜索树T一致。

分为三部分:

  1. 搜索树表示
  2. 建立搜索树T
  3. 判别一序列是否与搜索树T一致

搜索树表示

typedef struct TreeNode* Tree;
struct TreeNode
{
	int v;
	Tree Left, Right;
	int flag;
};

程序框架搭建

int main()
{
    对每组数据
        1.读入N和L
        2.根据第一行序列建树T
        3.依据树T分别判别后面的L个序列是否能与T形成同一搜索树并输出结果。
        return 0;
}

需要设计的主要函数:

  • 读数据建立搜索树T
  • 判别一序列是否与T构成一样的搜索树
int main()
{
	int N, L, i;
	Tree T;
	scanf("%d", &N);
	while (N)
	{
		scanf("%d", &L);
		T = MakeTree(N);
		for (i = 0; i < L; i++)
		{
			if (Judge(T, N))
				printf("Yes\n");
			else
				printf("No\n");
			ResetT(T); /*清除T中的所有标记flag*/
		}
		FreeTree(T);
		scanf("%d", &N);
	}
	return 0;
}

如何建搜索树

Tree MakeTree(int N)
{
	Tree T;
	int i, V;
	scanf("%d", &V);
	T = NewNode(V);
	for (i = 1; i < N; i++)
	{
		scanf("%d", &V);
		T = Insert(T,V);
	}
	return T;
}
Tree Newnode(int V)
{
	Tree T = (Tree*)malloc(sizeof(struct TreeNode));
	T->v = V;
	T->Left = T->Right = NULL;
	T->flag = 0;
	return T;
}

Tree Insert(Tree T, int V)
{
	if (!T)
		T = NewNode(V);
	else
	{
		if (V > T->v)
			T->Right = Insert(T->Right, V);
		else
			T->Left = Insert(T->Left, V);
	}
	return T;
}

如何判别

 

如何判别序列3  2  4  1是否与树T一致呢? 

方法

在树T中按顺序搜索序列3  2  4  1中的每个数:

  • 如果每次搜索所经过的结点在前面均出现过,则一致
  • 否则(某次搜索中遇到前面未出现过的结点),则不一致

 

查找函数

check函数接受两个参数:一个二叉搜索树T和一个整数V。

函数的返回值为整型。

在二叉搜索树T中查找整数V, 如果找到了,则将该结点的标记flag设为1,并返回1;

如果没有找到,则返回0。

用递归的方式:首先判断当前结点是否被标记,如果被标记,则根据V与当前结点的大小关系,递归地查找左子树或右子树。

如果当前结点未被标记,则判断V是否等于当前结点的值, 如果等于,则将该结点的标记设为1,并返回1;

否则返回0。

int check(Tree T, int V)
{
	if (T->flag)
	{
		if (V < T->v)
		{
			return check(T->Left, V);
		}
		else if (V > T->v)
		{
			return check(T->Right, V);
		}
		else
			return 0;
	}
	else
	{
		if (V == T->v)
		{
			T->flag = 1;
			return 1;
		}
		else
		{
			return 0;
		}
	}
}

判断函数

int Judge(Tree T, int N)
{
	int i, V;
	scanf("%d", &V);
	if (V != T->v)
	{
		return 0;
	}
	else
	{
		T->flag = 1;
	}
	for (i = 1; i < N; i++)
	{
		scanf("%d", &V);
		if (!check(T, V)) 
		return 0;
	}
	return 1;
}

函数有两个参数:一个是指向树的指针T,另一个是整数N。

首先从输入中读取一个整数V,如果V不等于树T的根结点值,则返回0, 表示输入的第一个数与树T不匹配。

如果V等于树T的根结点值,则将根结点的标记flag设置为1, 表示该节点已经被访问过。

接下来,用一个循环来读取剩余的N-1个整数。

对于每个整数V,函数调用check函数来检查树T中是否存在一个结点的值等于V。

如果不存在这样的节点,则返回0,表示输入的整数与树T不匹配。

如果存在这样的节点,则将该节点的标记flag设置为1, 表示该节点已经被访问过。

最后,如果所有的输入整数都能在树T中找到对应的节点,则返回1,表示输入的整数与树T匹配。

但是这段代码是存在bug的,当发现序列中的某个数与T不一致时,返回0程序结束,而不会把后面的数读完了。

那么就会误把后面的数当成下一组序列来看了,导致序列错乱了。

所以,当发现序列中的某个数与T不一致时,必须把序列后面的数都读完。

据此来改进代码:

int Judge(Tree T, int N)

{
	int i, V, flag = 0;

	/*flag:0代表目前还一致,1代表已经不一致*/

	scanf("%d", &V);

	if (V != T->v)flag = 1;
	else T->flag = 1;
	for (i = 1; i < N; i++)
	{
		scanf("%d", &V);
		if ((!flag) && (!check(T,V)))
			flag = 1;
	}
	if (flag) 
		return 0;
	else 
		return 1;
}

输入参数为一个指向二叉树根结点的指针T和一个整数N,表示序列的长度。

函数的返回值为1或0,表示给定的二叉树是否与序列匹配。

首先从输入中读取第一个整数V,表示序列中的第一个元素。

如果V与二叉树根结点的值不相等,则将flag(这里是函数内部的flag标记)标记为1,表示当前已经不一致了;

否则将根节点的flag(这里是结点内的flag标记,表示是否访问过)标记为1,表示已经匹配上了。

再循环读取序列中的剩余元素,每次读取一个整数V。

如果当前已经不一致了(即flag为1),则直接跳过后面的元素。

如果当前还一致,并且当前节点的值等于V,则将当前节点的flag标记为1,表示已经匹配上了;

否则将flag标记为1,表示当前已经不一致了。

循环结束后,如果flag为1,则说明序列与二叉树不匹配,返回0;

否则返回1,表示匹配成功。

其他函数

清除T中各结点的flag标记

void ResetT(Tree T) /*清除T中各结点的flag标记*/
{
	if (T->Left)
		ResetT(T->Left);
	if (T->Right)
		ResetT(T->Right);
	T->flag = 0;
}

先递归处理其左子树,再递归处理其右子树, 最后将该结点的flag标记设为0,表示清除标记。 这样,整个二叉树中所有节点的flag标记都被清除了。

释放T的空间

void FreeTree(Tree T) /*释放T的空间*/
{
	if (T->Left)
		FreeTree(T->Left);
	if (T->Right)
		FreeTree(T->Right);
	free(T);
}

end


学习自:MOOC数据结构——陈越、何钦铭

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/472590.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

libigl添加Viewer Menu时出现imgui相关的错误:无法打开包括文件: “imgui.h”: No such file or directory

libigl添加如下图所示的Viewer Menu时&#xff0c;出现了“无法打开包括文件: “imgui.h”: No such file or directory”的错误 很显然是libigl内嵌的imgui出了问题 从项目路径libigl-example-project-main\out\build\x64-Release\_deps\libigl-src\include\igl\opengl\glfw\…

【谷粒商城之CompletableFuture异步编排】

本笔记内容为尚硅谷谷粒商城CompletableFuture异步编排部分 目录 一、线程回顾 1 、初始化线程的 4 种方式 2.、线程池的七大参数 运行流程&#xff1a; 3、常见的4种线程池 4、开发中为什么使用线程池 二、CompletableFuture 异步编排 业务场景 1、创建异步对象 …

无线化超轻薄,香港城市大学体感反馈贴片WeTac

此前&#xff0c;青亭网曾报道香港城市大学与腾讯Robotics X Lab合作研发的低电压体感方案&#xff0c;原理是通过微电流刺激来模拟触觉&#xff0c;可模拟微小物体的体感。近期&#xff0c;香港城市大学的一组科研人员也公布了一项类似的方案&#xff1a;WeTac&#xff0c;该方…

轻松上手:使用VSCode调试Python模块级代码的完整教程

安装VSCode&#xff1a;请确保已经安装了Visual Studio Code。安装Python插件&#xff1a;在VSCode中&#xff0c;转到Extensions视图 (View -> Extensions) 并搜索"Python"。找到由Microsoft提供的插件并点击安装。重启VSCode以确保插件安装正确。准备项目&#…

边听歌边充电LDR6028+LDR9201既能充电又能OTG方案

随着type-c接口的普及&#xff0c;市面上的手机&#xff0c;平板&#xff0c;笔电逐渐都采用了type-c接口&#xff0c;设备为了不断的追求更轻薄的机身和防水要求慢慢的取消了一些影响手机外观完整性的接口&#xff0c;比如3.5mm耳机孔。 有线耳机用户一般会选择使用C口转3.5m…

资深架构师解读零代码开发平台—如何不写代码实现流程审批

审批节点 “审批节点&#xff1a;” 流程中涉及审批时&#xff0c;需要用到审批节点。审批可通过或者驳回&#xff0c;也可以发送通知。可以多人会签/或签审批。 1. 审批节点 1.1 审批设置 ① 审批方式 审批方式默认为或签方式&#xff0c;只一个人审批即可 当选择会签时&#…

【英语】大学英语CET考试,口语考试介绍与备考1(讲义笔记)

文章目录 1、考试基本信息2、考试题型介绍3.1 短文朗读与回答问题&#xff08;语音篇&#xff09;3.1.1 语音篇真题3.1.2 语音篇6项基础知识3.1.3 语音语调练习&#xff08;名言名句&#xff09;3.1.4 短文朗读练习材料&#xff08;真题&#xff09; 3.2 自我介绍与看图说话&am…

IC面试,你一定要准备好这些(内附大厂面试题目)

大家都知道&#xff0c;面试的表现会对于个人职业发展的重要性&#xff0c;不仅能决定是否录用&#xff0c;还会影响到后期的谈薪&#xff0c;所以面试前一定要做好充分的准备。 怎么准备面试&#xff1f; 这里就建议简历上的表述尽量客观化、专业化&#xff0c;多使用数字和…

目标跟踪综述 (持续更新)

这几天对目标跟踪挺感兴趣的&#xff0c;但是在CSDN和知乎上面找的相关介绍资料都看的一知半解&#xff0c;所以自己找了一篇 2022-04-26 发表的综述文章作下笔记学习下。 目录 一、基于相关滤波的目标跟踪算法 1、相关滤波视频目标跟踪算法的框架 2、相关滤波目标跟踪算法…

GPT-4开源平替miniGPT-4来了,仅需23G显存单机可run,附论文、项目代码地址

来源 | 新智元 微信号&#xff1a;AI-era 先是ChatGPT的发布给世界带来了一点小小的NLP震撼&#xff0c;随后发布的GPT-4更是破圈计算机视觉&#xff0c;展现了非凡的多模态能力。 不光能读懂人类的梗&#xff0c;给个手绘草图甚至可以直接写出网站的代码&#xff0c;彻底颠覆…

百度地图 TypeError: Cannot set properties of undefined (setting ‘Bm‘)

这类问题出现的原因一般是&#xff0c;页面还没有加载完&#xff0c;地图开始加载&#xff0c;或者地图加载在页面加载之前 在项目中&#xff0c;我用isMapLoading控制地图的加载&#xff0c;false–加载&#xff0c;true–不加载&#xff0c;在data()中设置isMapLoadingtrue

矩阵的秩的计算

definition 1 矩阵的秩 矩阵的列空间的维度 矩阵的零空间的秩 矩阵的自由变量的个数 n - r(A) definition 2 这两个证明很好证 第三个证明可以用零空间的秩 example 1 hyperlink

HTTPS建立连接原理、SSL工作原理

HTTPS与HTTP相比有什么区别&#xff1f; HTTPS保证安全的原理是什么&#xff1f; HTTPS是如何建立连接的&#xff1f; 巨人的肩膀 3.1 HTTP 常见面试题 | 小林coding HTTP与HTTPS的区别 HTTP是超文本传输协议&#xff0c;传输的内容是明文(HTTP1.1及之前版本)。HTTPS在TCP与HT…

【LeetCode】27. 移除元素

题目链接&#xff1a;https://leetcode.cn/problems/remove-element/ &#x1f4d5;题目要求&#xff1a; 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素&#xff0c;并返回移除后数组的新长度。 不要使用额外的数组空间&#xff0c;…

【原创】生成文件MD5图像,类似于GitHub的像素风格头像

前言 我想通过文件的md5生成关于这个md5的图像&#xff0c;类似于GitHub的随机像素头像&#xff0c;用处是让这个md5更加直观&#xff0c;也能用于生成各种用户头像&#xff0c;跟GitHub一样。 网上搜了一下&#xff0c;没有现成的方法&#xff0c;只能有一篇类似的文章可以借…

第N2周:中文文本分类-Pytorch实现

目录 一、前言二、准备工作三、数据预处理1.加载数据2.构建词典3.生成数据批次和迭代器 三、模型构建1. 搭建模型2. 初始化模型3. 定义训练与评估函数 四、训练模型1. 拆分数据集并运行模型 一、前言 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 …

运算符重载----赋值运算符重载

运算符重载 本质是函数调用&#xff0c;内置类型编译器直接比&#xff0c;自定义就去找对应类内重载的函数 如果定义在类外&#xff0c;需要访问私有的成员函数&#xff0c;只能将成员函数权限变为Public或者友元&#xff08;非必须不用&#xff09; &#xff0c;所以一般重载…

Linux程序设计之字节序转换

1.在网络通信中&#xff0c;数据的存储方式十分重要&#xff0c;因为它影响到数据的准确性。如今&#xff0c;电脑和网络上数据的存储方式有两种&#xff1a;大端模式和小端模式。大端模式&#xff1a;数据的高位存储在内存的低位&#xff0c;数据的低位存储在内存的高位。小端…

【keil5开发ARM工程时使用STLink调试的技巧分享】

ARM工程开发小技巧系列文章 St link V2驱动安装方法 文章目录 ARM工程开发小技巧系列文章前言一、准备工作1. 硬件连接2. 安装stlink的驱动3. Keil 5配置 二、调试示例1.进入调试状态2. 调试演示2.1 复位&#xff0c;使程序复位到初始位置2.2 单步调试2.3 逐步调试2.4 跳出调…

Quartus中的逻辑锁定与增量编译

逻辑锁定功能可以将FPGA中的代码模块在固定区域实现&#xff0c;优化时序性能&#xff0c;提升设计可靠性。增量编译功能&#xff0c;可以使设计更快速时序收敛&#xff0c;加快编译速度。 LogicLock 使用Chip Planner创建逻辑锁定区域 打开Chip Planner&#xff0c;点击Vie…