【数据结构】五分钟自测主干知识(十)

news2024/9/25 7:16:02

上一节,我们讲述了二叉树的概念,二叉树又有什么基本操作呢?今天我们来讲述二叉树的应用~

话不多说,书继上回


5.3二叉树的遍历及应用

二叉树由三个基本部分组成:根结点(D),左子树(L),右子树(R)。

因此,对二叉树的遍历可以分别对这三个部分进行。

如果遵循先左后右的原则,可以有三种遍历规则:DLR,LDR,LRD。

分别称为先序遍历中序遍历后序遍历

1.先序遍历

定义:若二叉树为空,则空操作,否则:

(1)访问根结点;

(2)先序遍历左子树;

(3)先序遍历右子树。

按照这个递归定义可以写出先序遍历二叉树的递归算法:

void PreOrder(BiTree T) {
	if (!T) return;
	visite(T->data);//访问根结点
	PreOrder(T->lchild);
	PreOrder(T->rchild);
}
2.中序遍历

定义:若二叉树为空,则空操作,否则:

(1)中序遍历左子树;

(2)访问根结点;

(3)中序遍历右子树。

按照这个递归定义可以写出中序遍历二叉树的递归算法:

void InOrder(BiTree T) {
	if (!T) return;
	InOrder(T->lchild);
	visite(T->data);//访问根结点
	InOrder(T->rchild);
}
3.后序遍历

定义:若二叉树为空,则空操作,否则:

(1)后序遍历左子树;

(2)后序遍历右子树。

(3)访问根结点;

按照这个递归定义可以写出后序遍历二叉树的递归算法:

void PostOrder(BiTree T) {
	if (!T) return;
	PostOrder(T->lchild);
	PostOrder(T->rchild);
	visite(T->data);//访问根结点
}

可见这三种遍历的搜索路线是一样的,只是访问根的时机不同。 

将二叉树上每个空子树用一个虚结点表示,将这样处理后的二叉树称为原二叉树的扩展二叉树

原二叉树上的结点称为内部结点,表示空指针的虚结点称为外部结点

递归算法优点是简洁,但一般而言,其执行效率不高,因为系统需要维护一个运行栈以保证递归过程是正确执行。其实以上遍历还可以使用非遍历方法。

设一存放结点指针的栈S,每访问完一个结点X后,就将结点X的指针入栈,以便后来能通过这个指针找到结点X的右子树。

void PreOrder(BiTree T) {
	InitStack(S);    //初始化一个空栈
	while (T || !StackEmpty(S)) {//遍历结束的条件是栈为空且T为空
		while (T) {
			visite(T->data);
			Push(S, T);    //T进栈
			T = T->lchild;
		}
		if (!StackEmpty(S)) {
			Pop(S, T);    //弹出栈顶指针T
			T = T->rchild;
		}
	}
}

其中有关栈的处理(其中一些函数)详见前面的文章

附链接:【数据结构】五分钟自测主干知识(四)http://t.csdnimg.cn/DffSWicon-default.png?t=N7T8http://t.csdnimg.cn/DffSW


 4.层序遍历

对二叉树除了可以按上述的先序、中序和后序规则进行遍历外,还可以自上而下,自左向右逐层地进行遍历。

在层序遍历时,当第 i 层结点被访问完后,接下来要逐个访问位于第i + 1 层上的第 i 层结点的左孩子和右孩子。这时,在 i层先被访问的结点其左、右孩子将先被访问,因此需要利用一个队列来存放已访问过的结点的孩子,以控制对这些孩子的访问先后次序。层序遍历的算法思路是:


(1)初始化一个空队列,用来保存已访问过结点的孩子;


(2)非空根指针入队;


(3)若队列为空,则遍历结束;否则重复执行:
①队头元素出队,访问之;
②若被访结点有左孩子,则左孩子入队;
③若被访结点有右孩子,则右孩子入队。

void LayerTraversal(BiTree T) {
	InitQueue(Q);
	if (T) EnQueue(Q, T);
	while (!QueueEmpty(Q)) {
		DeQueue(Q, p);
		visite(p->data);
		if (p->lchild) EnQueue(Q, p->lchild);
		if (p->lchild) EnQueue(Q, p->rchild);
	}
}

其中有关队列的处理(其中一些函数)详见前面的文章

附链接:【数据结构】五分钟自测主干知识(五)
http://t.csdnimg.cn/TX4HAicon-default.png?t=N7T8http://t.csdnimg.cn/TX4HA

不论按哪种次序遍历含有n个结点的二叉树,其时间复杂度至少为O(n)


5.二叉树运算举例

1.求二叉树的结点个数

方案1:

int CountNodes1(BiTree T) {
	if (!T) return 0;
	int nl = CountNodes1(T->lchild);
	int nr = CountNodes1(T->rchild);
	return(1 + nl + nr);
}

方案2:

void CountNodes2(BiTree T, int& n) {
	if (!T)return;
	n++;
	CountNodes2(T->lchild, n);
	CountNodes2(T->rchild, n);
}

2.输出二叉树每个结点的层次数

void Level(BiTree T, int lev){
	if (!T)return;
	lev++;
	printf(T->data,lev);
	Level(T->lchild, lev);
	Level(T->rchild, lev);
}

3.求二叉树的深度

好用的递归方法继续:

int Depth(BiTree T) {
	if (!T)return 0;
	int hl = Depth(T->lchild);
	int hr = Depth(T->rchild);
	return (hl > hr ? hl + 1: hr + 1);
}

4.输出二叉树树根到所有叶子结点的路径

void OutPath(BiTree T, Stack& S) {
	if (!T)return;
	Push(S, T);
	if (!T->lchild && !T->rchild)
		StackTraverse(S);
	OutPath(T->lchild, S);
	OutPath(T->rchild, S);
	Pop(S, e);
}

5.(重点)表达式求值

算术表达式可以用二叉树的形式来表示。

用二叉树表示算术表达式的递归方法如下:

(1)如果表达式为常数或简单变量,则二叉树中仅有一个根结点,根结点的数据域存放该表达式的值。

(2)如果表达式的形式是:

(左操作数) 二目运算符 (右操作数)

则二叉树中,以左子树表示左操作数,右子树表示右操作数,根结点的数据域存放二目运算符。

(3)操作数本身又是表达式

例如表达式a+b*(c-d)-e/f的二叉树表示如下:

该二叉树的先序序列为-+a*b-cd/ef

恰好是表达式的前缀表示(波兰式

该二叉树的后序序列为abcd-*+-ef/

恰好是表达式的后缀表示(逆波兰式

 下面给出表达式二叉树结点的存储类型定义:

typedef struct BiNode {
	double val;
	char op;
	unsigned char tag;
	struct BiNode* lchild, * rchild;
}BiTNode,*BiTree;

其中val分量用来存放表达式中的数值,op分量用来存放表达式中的运算符。

tag起标志作用,若tag=0,则表示结点中存放的是数值,取val分量;

若tag=1,则表示结点中存放的是运算符,取op分量。

对表达式求值可用逆波兰式的求值方法,即利用后序遍历完成计算

double Calculate(BiTree T) {
	if (T->tag == 0)return T->val;
	double a = Calculate(T->lchild);
	double b = Calculate(T->rchild);
	return operate(a, T->op, b);//计算并返回a op b
}

其中operate函数表示计算算式值


今天我们就到这里,可以对照黑体字查看主干知识,下一讲,我们聊聊线索二叉树

附链接:【数据结构】五分钟自测主干知识()

长咕一下

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

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

相关文章

ZooKeeper 的常见应用场景

数据发布与订阅 发布与订阅即所谓的配置管理,顾名思义就是将数据发布到ZooKeeper节点上,供订阅者动态获取数据,实现配置信息的集中式管理和动态更新。例如全局的配置信息,地址列表等就非常适合使用。 数据发布/订阅的一个常见的…

Spring Boot:基础配置

Spring Boot 全局配置文件application.propertiesapplication.yml全局配置文件的优先级 从全局配置文件中获取数据的注解从外部属性文件中获取数据的注解全局配置文件的配置项通用配置项数据源配置项JPA 配置项日志配置项配置文件特定配置项Profile 特定配置项 配置类配置文件中…

【Emgu CV教程】10.4、轮廓之多边形近似拟合

文章目录 一、什么叫轮廓的多边形近似拟合二、轮廓的多边形近似拟合函数三、简单应用1.原始素材2.代码3.运行结果 一、什么叫轮廓的多边形近似拟合 轮廓一般都是光滑的曲线,多边形近似拟合的意思就是,利用少量的点组成的折线,近似逼近原始多…

AIGC实战——Transformer模型

AIGC实战——Transformer模型 0. 前言1. T52. GPT-3 和 GPT-43. ChatGPT小结系列链接 0. 前言 我们在 GPT (Generative Pre-trained Transformer) 一节所构建的 GPT 模型是一个解码器 Transformer,它逐字符地生成文本字符串,并使用因果掩码只关注输入字…

力扣98---验证二叉搜索树

题目描述: 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下: 节点的左 子树 只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 …

计算联合体union的大小

一:联合类型的定义 联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体) 比如:共用了 i 这个较大的空间 二: 联合的特点 …

YoloV8改进策略:Block改进|PKINet

摘要 PKINet是面向遥感旋转框的主干,网络包含了CAA、PKI等模块,给我们改进卷积结构的模型带来了很多启发。本文使用PKINet的Block替换YoloV8的Block,实现涨点。改进方法是我独创首发,给写论文没有思路的同学提供改进思路,欢迎大家订阅! 论文:《Poly Kernel Inception …

需求:实现一个类似打印的效果(文字一个字一个字的输出)

实现效果: 需求:最近接到这么一个需求,ai机器人回复的问题,后端是通过websocket每隔一段事件返回数据,前端拿到数据后直接渲染,现在需要做到一个效果,后端返回的结果前端需要一个一个文字的输出…

Unity Canvas的三种模式

一、简介: Canvas的Render Mode一共有三种模式:Screen Space -OverLay、Screen Space-Camera、World Space Screen Space - Overlay(屏幕空间 - 覆盖): 这是最简单的 Canvas 渲染模式。UI 元素在这个模式下将渲染在屏…

使用amd架构的计算机部署其他架构的虚拟机(如:arm)

1 下载quem模拟器 https://qemu.weilnetz.de/w64/2 QEMU UEFI固件文件下载(引导文件) 推荐使用:https://releases.linaro.org/components/kernel/uefi-linaro/latest/release/qemu64/QEMU_EFI.fd3 QEMU 安装 安装完成之后,需要将安装目录添加到环境变…

flutter3_douyin:基于flutter3+dart3短视频直播实例|Flutter3.x仿抖音

flutter3-dylive 跨平台仿抖音短视频直播app实战项目。 全新原创基于flutter3.19.2dart3.3.0getx等技术开发仿抖音app实战项目。实现了类似抖音整屏丝滑式上下滑动视频、左右滑动切换页面模块,直播间进场/礼物动效,聊天等模块。 运用技术 编辑器&#x…

C语言字节对齐关键字#pragma pack(n)的使用

0 前言 在进行嵌入式开发的过程中,我们经常会见到对齐操作。这些对齐操作有些是为了便于实现指针操作,有些是为了加速对内存的访问。因此,学习如何使用对齐关键字是对于嵌入式开发是很有必要的。 1 对齐规则 1.0 什么叫做对齐 众所周知&a…

微服务(基础篇-003-Nacos集群搭建)

目录 Nacos集群搭建 1.集群结构图 2.搭建集群 2.1.初始化数据库 2.2.下载nacos 2.3.配置Nacos 2.4.启动 2.5.nginx反向代理 2.6.优化 视频地址: 06-Nacos配置管理-nacos集群搭建_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1LQ4y127n4?p29&…

操作系统究竟是什么?在计算机体系中扮演什么角色?

操作系统究竟是什么?在计算机体系中扮演什么角色? 一、操作系统概念二、操作系统如何管理软硬件资源2.1 何为管理者2.2 操作系统如何管理硬件 三、系统调用接口作用四、用户操作接口五、广义操作系统和狭义操作系统 一、操作系统概念 下面是来自百度百科…

Springboot做分组校验

目录 分组校验 Insert分组 Upload分组 测试接口 测试结果 添加测试 更新测试 顺序校验GroupSequence 自定义分组校验 自定义分组表单 CustomSequenceProvider 测试接口 测试结果 Type类型为A Type类型为B 总结: 前文提到了做自定义的校验注解&#xff…

React高阶组件(HOC)

高阶组件的基本概念 高阶组件(HOC,Higher-Order Components)不是组件,而是一个函数,它会接收一个组件作为参数并返回一个经过改造的新组件: const EnhancedComponent higherOrderComponent(WrappedCompo…

小游戏-扫雷

扫雷大多人都不陌生,是一个益智类的小游戏,那么我们能否用c语言来编写呢, 我们先来分析一下扫雷的运行逻辑, 首先,用户在进来时需要我们给与一个菜单,以供用户选择, 然后我们来完善一下&#…

解决方案Please use Oracle(R) Java(TM) 11, OpenJDK(TM) 11 to run Neo4j.

文章目录 一、现象二、解决方案 一、现象 当安装好JDK跟neo4j,用neo4j.bat console来启动neo4却报错: 部分报错信息: Starting Neo4j. WARNING! You are using an unsupported Java runtime. Please use Oracle Java™ 11, OpenJDK™ 11 t…

Rust下载安装、卸载、版本切换、创建项目(包含指定版本的)

先声名一下,下面所说的版本号为xxxxx-x86_64-unknown-linux-gnu中xxxxx的部分。 下载安装 下载最新版本的Rust: curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh info: downloading installer重启shell 或者 按照提示 执行命令让环境变…

Day56-LNMP架构扩展为集群模式实战精讲

Day56-LNMP架构扩展为集群模式实战精讲 1. 企业级标准部署知乎产品wecenter1.1 部署知乎软件Wecenter 2. 企业级迁移数据库到独立服务器2.1 为什么要进行数据库的拆分2.2 数据库拆分架构演变过程,如下图所示2.3 数据库拆分环境规划2.4 数据库拆分架构详细步骤2.4 we…