二叉树创建和遍历

news2024/11/9 1:54:49
个人主页    :敲上瘾-CSDN博客
二叉树介绍:二叉树(详解)-CSDN博客

目录

一、二叉树的创建

二、二叉树的遍历

1.前序遍历

2.中序遍历

3.后序遍历

4.层序遍历

三、相关计算

1.总节点个数计算

2.叶子节点个数计算

3.深度计算


一、二叉树的创建

        关于二叉树的创建和遍历我们考虑用递归来实现。
        我们通过前序遍历的数组"ABD##E#H##CF##G##" 来创建数组,其中 '#' 相当于空指针。

头文件的声明:

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType _data;
	struct BinaryTreeNode* _left;
	struct BinaryTreeNode* _right;
}BTNode;
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi)
{
	if (*pi == n)
		return NULL;
	int val = a[(*pi)++];
	if (val == '#')
		return NULL;
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	assert(root);
	root->_data = val;
	root->_left = BinaryTreeCreate(a, n, pi);
	root->_right = BinaryTreeCreate(a, n, pi);
	return root;
}

二、二叉树的遍历

        学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的结点进行相应的操作,并且每个结点只操作一次。访问结点所做的操作依赖于具体的应用问题。

        遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:
        1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
        2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
        3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

1.前序遍历

void BinaryTreePrevOrder(BTNode* root)
{
	if (!root)
	{
		printf("#");
		return;
	}
	printf("%c", root->_data);
	BinaryTreePrevOrder(root->_left);
	BinaryTreePrevOrder(root->_right);
}
//或者这么写:
void PrevOrder(BTNode* root)
{
	if (root)
	{
    	printf("%c", root->_data);
    	PrevOrder(root->_left);
	    PrevOrder(root->_right);
    }
}

2.中序遍历

void BinaryTreeInOrder(BTNode* root)
{
	if (!root)
	{
		printf("#");
		return;
	}
	BinaryTreeInOrder(root->_left);
	printf("%c", root->_data);
	BinaryTreeInOrder(root->_right);
}

3.后序遍历

void BinaryTreePostOrder(BTNode* root)
{
	if (!root)
	{
		printf("#");
		return;
	}
	BinaryTreePostOrder(root->_left);
	BinaryTreePostOrder(root->_right);
	printf("%c", root->_data);
}

4.层序遍历

        层序遍历是一层一层往下遍历的,并不是单个方向深入,像以上三种遍历都可以叫做深度优先遍历,而层序遍历也可以叫做广度优先遍历,它是不能用递归实现的,要实现它我们可以使用一个队列结构,我们把根节点存入队列然后对队列进行操作,把根节点拿出来(Pop)然后把它的左孩子和右孩子依次取出放入队列,然后再次从队头取到根节点重复操作,一次下去直到队列为空,就能完成层序遍历。如下:

void BinaryTreeLevelOrder(BTNode* root)
{
	if (!root)
		return;
	Queue pt;//需要构造出一个队列结构,这里就不在展示
	QueueInit(&pt);
	QueuePush(&pt, root);
	while (!QueueEmpty(&pt))
	{
		BTNode* pf = QueueFront(&pt);
		if (pf)
			printf("%c", pf->_data);
		else
			printf("#");
		QueuePop(&pt);
		if (pf)
		{
			QueuePush(&pt, pf->_left);
			QueuePush(&pt, pf->_right);
		}
	}
}

三、相关计算

1.总节点个数计算

        在计算节点个数的时候,初学着可能会想用一个全局变量,用以上任意方法遍历并计数。这种方法是可行的但不太可靠。像这些二叉树相关的计算我们大多数都可以考虑把它化为小问题去分析。如果是空树的话就是0,如果不是空树就是1+左树的节点个数+右树的节点个数,像这样左树又可以分为左树和右树去解决,可以不断的把问题化小。如下:

int BinaryTreeSize(BTNode* root)
{
	if (!root)
		return 0;
	else
		return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}

2.叶子节点个数计算

这个计算和上一个方法是相似的,不过我们得特别判断以下是否为叶子节点。如下:

int BinaryTreeLeafSize(BTNode* root)
{
	if (!root)
		return 0;
	if (!root->_left && !root->_right)
		return 1;
	return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

3.深度计算

        求一颗树的深度可以化为就是左子树的深度和右子树中的最大深度,而左子树又可以在化为更小的左右子树的深度就如此递推下去,直到遇到空树才一次回归(返回),这样就把大问题化为小问题用递归实现。如下:

int BinaryTreeHeight(BTNode* root)
{
	if (!root)
		return 0;
	int v1=BinaryTreeHeight(root->_left);
	int v2 = BinaryTreeHeight(root->_right);
	return v1 > v2 ? v1 + 1 : v2 + 1;
}

要注意一点的是千万不要写成下面的方式: 

这样会使一个函数内就有三个递归展开,效率会变得非常非常低。 

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

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

相关文章

Lodop 实现局域网打印

文章目录 前言一、Lodop支持打印的方式lodop 打印方式一般有3种:本地打印局域网集中打印广域网AO打印 二、集成步骤查看lodop 插件的服务端口:查看ip后端提供接口返回ip,前端动态获取最后步骤 前言 有时候会根据不同的ip来获取资源文件&…

天锐绿盾 | 源代码防泄密软件

#源代码防泄密# 天锐绿盾是一款专为企业设计的,旨在保护企业核心数据安全与防止代码泄露的软件。它通过一系列技术手段实现对信息的加密、访问控制、行为审计、外发控制等,以确保企业内部的代码和敏感信息不会未经授权就被泄露出去。 PC地址&#xff1a…

音视频开发19 FFmpeg 视频解码- 将 h264 转化成 yuv

视频解码过程 视频解码过程如下图所示: ⼀般解出来的是420p FFmpeg流程 这里的流程是和音频的解码过程一样的,不同的只有在存储YUV数据的时候的形式 存储YUV 数据 如果知道YUV 数据的格式 前提:这里我们打开的h264文件,默认是YU…

电子元器件采购商城的售后服务保障

电子元器件采购商城的售后服务保障是用户在采购电子元器件时的重要考量因素之一。以下是常见的售后服务保障内容: 退换货政策: 质量问题退换货:如果用户收到的元器件存在质量问题,通常可以在一定时间内申请退换货。无理由退换货&a…

Linux--Socket编程基础

一、Socket简介 套接字( socket )是 Linux 下的一种进程间通信机制( socket IPC ), 使用 socket IPC 可以使得在不同主机上的应用程序之间进行通信(网络通信),当然也可以是同一台…

【C++课程学习】:C++入门(输入输出,缺省参数)

🎁个人主页:我们的五年 🔍系列专栏:C课程学习 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 🍩1.关于C输入输出: 🍩2.缺省参数函数: 缺省参数的概…

手上3个offer怎么选,深信服的技服、奇安信的安全服务、绿盟的渗透工程师

我是一个应届生,目前手上收到了3个offer比较纠结选哪个? 1、深信服技术服务工程师,base 西安,月薪 14k 据说还有些异地补助 2、奇安信安全服务工程师,base 重庆,月薪 12k 3、绿盟科技的渗透工程师&#…

轻松掌握PDF文本内容修改技巧,让文档编辑更高效便捷,职场工作从此得心应手!

在快节奏的职场生活中,PDF文档已经成为我们工作中不可或缺的一部分。然而,如何高效、便捷地修改PDF文本内容,一直是许多职场人士头疼的问题。今天,就让我来为你介绍一款神奇的编辑工具——首助编辑高手,它将帮助你轻松…

http://app.hrss.xm.gov.cn/xmggfw/index

厦门市人力资源和社会保障局 厦门市国际职业资格比照认定职称审批表

【Cesium4UE】使用问题及解法统计

本期作者:尼克 易知微3D引擎技术负责人 1.加载3dtiles模型很慢 1.3dtiles是否做了重建顶层处理。如果3dtiles的tiles块太多使用CesiumLab重建顶层。 2.将3dtiles模型放置到固态硬盘中 3.如果有多块3dtiles,考虑使用CesiumLab合并3dtiles处理 4.如果不需…

14本剔除!Scopus目录第四次更新,Hindawi期刊再次上榜

【SciencePub学术】近期,Scopus数据库迎来本年度第四次更新!此次更新后,有89本期刊发生变动: 变动详情 •【新增】75本新增期刊进入Scopus数据库 •【剔除】14本期刊被Scopus数据库剔除 目前Scopus 来源出版物列表(…

Apple - Image I/O Programming Guide

翻译自:Image I/O Programming Guide(更新时间:2016-09-13 https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/ImageIOGuide/imageio_intro/ikpg_intro.html#//apple_ref/doc/uid/TP40005462 文章目录 …

关于教务排课的那些事

在办学过程中,你是否被如下问题困扰? 1、排课功率低: 为了确保师资资源得到充分利用,教务教师排课要求了解每一个全职和兼职教师,了解每一个人的时刻组织和带班状况,因而在排课的时分需求处理很多的信息&a…

InnoDB存储引擎非常重要的一个机制--MVCC(多版本并发控制)

Mysql是如何实现隔离性的?(锁MVCC) 隔离性是指一个事务内部的操作以及操作的数据对正在进行的其他事务是隔离的,并发执行的各个事务之间不能相互干扰。隔离性可以防止多个事务并发执行时,可能存在交叉执行导致数据的不…

Sketch语言设置指南:将英文版改成中文版的教程

Sketch版本的转换一直是困扰大家的关键问题。如今UI设计领域的UI设计软件很多,但大部分都是英文版。对于国内英语基础差的设计师来说,使用这样的软件无形中增加了工作量,往往需要在设计编辑的同时查阅翻译。即时设计详细介绍了Sketch英文版如…

夏季高温来袭|危化品如何安全储存?

《危险化学品安全管理条例》第三条 本条例所称危险化学品,是指具有毒害、腐蚀、爆炸、燃烧、助燃等性质,对人体、设施、环境具有危害的剧毒化学品和其他化学品。 随着夏天高温的来袭,炎热的天气对危化品储存威胁巨大,危化品事故也…

3. QGis二次开发项目实践一之解决“无法定位程序输入点“

前言 本章讲述实现本项目实现过程中遇到的QGis二次开发库版本和Qt以及其他动态库的版本匹配问题问题复现 本项目是要作为一个子模块集成到用户的项目中本项目最初的开发环境为QGis3.28+Qt5.15.2,而当时并未问清楚用户开发环境所以交付给用户之后,出现了类似下图的问题 出现该…

m1系列芯片aarch64架构使用docker-compose安装seata

之前看到 DockerHub 上发布了 m1 芯片 aarch64 架构的 seata 镜像, 所以就尝试的安装了下, 亲测可用: 使用该命令查看正在运行的 seata 容器 docker ps | grep seata 一. docker-compose.yml 命令编写 volumes 命令所指定的宿主机映射地址, 需要根据自己的电脑环境更换 环…

windows设置网络共享目录

在一个局域网内的计算机,我们想要共享一些资料,如何操作呢?下面我将用windows系统中的网络共享功能实现。 设置共享目录 首先在一台服务器或者计算机上新建一个文件夹(或者直接找一个空的分区)作为共享的目录&#x…

神经网络 torch.nn---Non-Linear Activations (ReLU)

ReLU — PyTorch 2.3 documentation torch.nn - PyTorch中文文档 (pytorch-cn.readthedocs.io) 非线性变换的目的 非线性变换的目的是为神经网络引入一些非线性特征,使其训练出一些符合各种曲线或各种特征的模型。 换句话来说,如果模型都是直线特征的…