数据结构入门(C语言版)二叉树链式结构的实现

news2024/11/20 7:02:19

在这里插入图片描述

二叉树链式结构的实现

  • 二叉树的概念及结构创建
    • 1、概念
    • 2、结构创建
    • 2、创建结点函数
    • 3、建树函数
  • 二叉树的遍历
    • 1、前序遍历
    • 2、中序遍历
    • 3、后序遍历
    • 4、层序遍历
  • 二叉树的销毁
  • 结语

二叉树的概念及结构创建

1、概念

简单回顾一下二叉树的概念:
★ 空树
★非空:根节点,根节点的左子树、根节点的右子树组成的。

在这里插入图片描述
在这里插入图片描述
从概念中可以看出,二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的。

2、结构创建

下面我们先看二叉树的结构体定义以及创建

typedef char BTDataType;
typedef struct BinaryTreeNode
{
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
	BTDataType data;
}BTNode;

首先结构体的定义是元素本身,以及左右子树的指针。

2、创建结点函数

BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	node->data = x;
	node->left = node->right = NULL;
	return node;
}

我们指定每调用一次此函数,便新建一个结点空间,并将左右指针指向空即可。

3、建树函数

BTNode* CreatBinaryTree()
{
	BTNode* nodeA = BuyNode('A');
	BTNode* nodeB = BuyNode('B');
	BTNode* nodeC = BuyNode('C');
	BTNode* nodeD = BuyNode('D');
	BTNode* nodeE = BuyNode('E');
	BTNode* nodeF = BuyNode('F');

	nodeA->left = nodeB;
	nodeA->right = nodeC;
	nodeB->left = nodeD;
	nodeC->left = nodeE;
	nodeC->right = nodeF;

	return nodeA;
}

这个函数是树建立的关键步骤,将每个结点创建完成后,再将每个结点的左右指针重定义,继而完成建树,上述代码执行后表示的就是下图:
在这里插入图片描述

二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
在这里插入图片描述

主要分为以下几种:

1、前序遍历

前序遍历(Preorder Traversal | 先序遍历)——访问根结点的操作发生在遍历其左右子树之前,顺序为:根 ->左子树->右子树
比如上面这个二叉树前序遍历输出为:
A B D NULL NULL NULL C E NULL NULL F NULL NULL
实现代码如下:

void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	printf("%c ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}

这个函数的实现是利用前序的性质,首先取根节点,之后每个结点先返回左结点,再返回右结点的顺序,进行递归调用,到最后的叶子结点之后再逐个返回打印输出,即为前序遍历。

2、中序遍历

中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中。
顺序为:左子树 ->根->右子树
比如这个二叉树中序遍历输出为:
NULL D NULL B NULL A NULL E NULL C NULL F NULL
实现代码如下:

void InOrder(BTNode* root)
{
	if (root == NULL){
		printf("NULL ");
		return;
	}

	InOrder(root->left);
	printf("%C ", root->data);
	InOrder(root->right);
}

中序遍历就是将前序稍微做调整,先打印左子树,再打印根,之后才是右子树,同样用的是递归分治。

3、后序遍历

后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。
顺序为:左子树 ->右子树->根
比如这个二叉树中序遍历输出为:
NULL NULL D NULL B NULL NULL E NULL NULL F C A
实现代码如下:

void PostOrder(BTNode* root)
{
	if (root == NULL){
		printf("NULL ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%C ", root->data);
}

此函数与上面两个同理而得。

4、层序遍历

除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
在这里插入图片描述
比如这个二叉树,层序遍历结果为123456。
代码实现如下:

void BinaryTreeLevelOrder(BTNode* root)
{
	if (root == NULL)
		return;

	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", front->data);

		if (front->left)
			QueuePush(&q, front->left);

		if (front->right)
			QueuePush(&q, front->right);
	}
	printf("\n");

	QueueDestroy(&q);
}

因为是链式结构,这里的层序遍历采用队列来实现,不了解队列的小伙伴可以看看我之前的文章:栈和队列之队列的介绍及实现
首先我们建立一个队列,初始化后先入根,再出根打印,继续打印其左右结点,继而循环打印,直到为空终止,最后释放队列空间,完成层序遍历打印。

二叉树的销毁

代码如下:

void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
	{
		return;
	}

	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}

销毁与前中后序的实现一样,使用递归自下而上销毁。

结语

有兴趣的小伙伴可以关注作者,如果觉得内容不错,请给个一键三连吧,蟹蟹你哟!!!
制作不易,如有不正之处敬请指出
感谢大家的来访,UU们的观看是我坚持下去的动力
在时间的催化剂下,让我们彼此都成为更优秀的人吧!!!

在这里插入图片描述

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

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

相关文章

intellij 从2020升级到2023 踩坑实录

1.下载新版本intellij 工作机器上的intellij版本为2020社区版,版本比较老旧,需要进行升级。IDE这种提高生产力的工具,还是蛮重要的,也是值得稍微多花点时间研究一下的。升级之前就预计到了不会是那么简单,后面事实也证…

大型体检管理系统源码,Vs2012,C/S架构

体检管理系统源码,PEIS源码 一套专业的体检管理系统源码,核心功能有体检档案的录入、体检报告的输出、体检档案的统计查询和对比分析。该系统的使用,可以大大提高体检档案管理人员的工作效率,使体检档案的管理更加准确、全面、完…

以人为本的重点是有效网络安全计划的关键

安全和风险管理 (SRM) 领导者在根据九大行业趋势创建和实施网络安全计划时,必须重新考虑他们在技术和以人为本的元素之间的投资平衡。 以人为本的网络安全方法对于减少安全故障至关重要。 在控制设计和实施以及通过业务沟通和网络安全人才管理中关注人&#xff…

Python中的异常——概述和基本语法

Python中的异常——概述和基本语法 摘要:Python中的异常是指在程序运行时发生的错误情况,包括但不限于除数为0、访问未定义变量、数据类型错误等。异常处理机制是Python提供的一种解决这些错误的方法,我们可以使用try/except语句来捕获异常并…

基于linux:MySql-5.7二进制安装部署

基于linux:MySql-5.7二进制安装 1)检查当前系统是否安装过Mysql [ ~]$ rpm -qa|grep mariadb mariadb-libs-5.5.56-2.el7.x86_64 //如果存在通过如下命令卸载 [ ~]$ sudo rpm -e --nodeps mariadb-libs //用此命令卸载mariadb2)解压MySQ…

限流算法浅析

前言 在前文接口请求安全措施中,简单提到过接口限流,那里是通过Guava工具类的RateLimiter实现的,它实际上是令牌桶限流的具体实现,那么下面分别介绍几种限流算法,做一个更详细的了解。 固定窗口限流 1、核心思想 在…

基于 Flink CDC 的现代数据栈实践

摘要:本文整理自阿里云技术专家,Apache Flink PMC Member & Committer, Flink CDC Maintainer 徐榜江和阿里云高级研发工程师,Apache Flink Contributor & Flink CDC Maintainer 阮航,在 Flink Forward Asia 2022 数据集成…

初识C语言————4

文章目录 常见关键字 1、 关键字 typedef 2、关键字static define 定义常量和宏 指针 结构体 前言 这是博主初识C语言系列的最后一篇,之后博主会更新更详细的关于C语言学习的知识。希望各位老铁多多支持。 一、常见关键字 1、 关键字 typedef typedef 顾名思义是…

海康威视发布2022年ESG报告:科技为善, 助力可持续的美好未来

近日,海康威视正式发布《2022环境、社会及管治报告》(以下简称“海康威视ESG报告”),连续5年呈现在环境、社会发展、企业治理等领域的思考和创新成果。此外,报告中首次披露了碳中和业务蓝图,积极布局绿色生产、绿色运营…

HTTP特性

1 HTTP/1.1 的优点有哪些? 2 HTTP/1.1 的缺点有哪些? 3 HTTP/1.1 的性能如何? HTTP 协议是基于 TCP/IP,并且使用了「请求 - 应答」的通信模式,所以性能的关键就在这两点里。 3.1 长连接 早期 HTTP/1.0 性能上的一…

分布式Id生成之雪花算法(SnowFlake)

目录 前言 回顾二进制 二进制概念 运算法则 位(Bit) 字节(Byte) 字符 字符集 二进制原码、反码、补码 有符号数和无符号数 疑问:为什么不是-127 ~ 127 ? 为什么需要分布式全局唯一ID…

sql中 join 的简单用法总结(带例子)

join 常见的用法有: 目录 left join(left outer join)right join(right outer join)join(inner join)full join(full outer join 、outer join)cross join 说明&#xf…

docker自定义镜像

文章目录 一、自定义镜像1.1 镜像结构1.2 Dockerfile1.3 dockerCompose1.3.1 dockerCompose的作用1.3.2 dockerCompose的常用命令 1.4 镜像仓库 一、自定义镜像 1.1 镜像结构 自定义镜像通常包含三个基本部分:基础镜像、应用程序代码和配置文件。 基础镜像&#…

asp.net+sqlserver+C#网上洗衣店的设计与实现

选题的目的、理论与实践意义: 随着洗衣店服务的日渐完善和复杂,以前单纯的文本记录人工管理方式不仅效率低下,且易出错,直接导致管理费用的增加,服务质量的下降。由于这种人工管理方式不能完全适应需求的发展&#xff…

打包后dist包中app.**.js文件暴露大量接口信息,webpack-obfuscator对打包后的js代码混淆加密

问题描述 打包后dist包中app.**.js文件暴露大量接口信息,而webpack-obfuscator可以对打包后的js代码混淆加密 版本信息 webpack: 4.x.x node: 14.18.0 webpack4环境下使用webpack-obfuscator不能使用最新版本 我的下载版本是: npm install --save-de…

回溯算法模板(python)

#回溯模板,伪代码 def backtracking(参数):if (终止条件):存放结果return #如果要将数层中间的结果也插入,就不用写return,比如子集问题for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)):处…

通过Python的PIL库进行图像的过滤

文章目录 前言一、素材准备二、演示1.引入库2.定义图片路径3.打开原图4.过滤方法4.1图像的模糊效果代码效果图 4.2图像的轮廓效果代码效果图 4.3图像的细节效果代码效果图 4.4图像的边界效果代码效果图 4.5图像的边界加强效果代码效果图 4.6图像的阈值边界加强效果代码效果图 4…

自定义bean对象实现hadoop序列化

文章目录 一、源代码1.UserSaleMapper类2. UserSaleReducer类3. UserSaleDriver类4.pom.xml 二、执行结果 指导参考图: 一、源代码 1.UserSaleMapper类 package org.example.writable;import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Tex…

大厂对ChatGPT的开发利用和评估案例收录

ChatGPT已经进入各行各业,但是实际在工作中的有哪些应用呢?这里分享互联网一线大厂分享的一些实际使用案例,所有文章收录到 大厂对ChatGPT的开发利用和评估案例收录http://​www.webhub123.com/#/home/detail?projectHashid67792343&own…

Visual Studio 2019 C# 上位机入门(2):写一个简单的串口助手

前言 本文记录一下用Visual Studio 2019 C# 写一个简单的串口助手的过程,由于没有先从小处学习,而是直接找相关资料就开始做,免不了很多奇怪的问题花了一些时间,基于此情况,我将尽可能整理出更多细节,尤其…