【数据结构】二叉树链式结构

news2024/11/27 12:32:39

在这里插入图片描述

🚀write in front🚀
📜所属专栏:初阶数据结构
🛰️博客主页:睿睿的博客主页
🛰️代码仓库:🎉VS2022_C语言仓库
🎡您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!
关注我,关注我,关注我你们将会看到更多的优质内容!!

在这里插入图片描述

文章目录

  • 前言
  • 一.二叉树的理解:
  • 二.二叉树的遍历:
    • 创建二叉树:
    • 1.前序遍历:
    • 2.中序遍历:
    • 3.后序遍历:
    • 4.层序遍历:
  • 三.判断二叉树是否为完全二叉树:
  • 四.二叉树结点数量:
      • 分治和遍历的区别:
  • 五.二叉树的高度(深度):
  • 六.二叉树第k层节点个数
  • 总结

前言

  在之前的二叉树的顺序结构中我们发现,该二叉树对于堆(一种完全二叉树)非常实用,但是对于非完全二叉树就会出现以下的结构,造成空间浪费:
在这里插入图片描述
  所以这里我们还是要通过链式结构来实现二叉树。但是其实普通二叉树是没有什么意义的,增删查改没有多大的意义。真正有意义的是搜索二叉树:
在这里插入图片描述
  搜索二叉树的特点是左子树比根大/小,右子树比根小/大。这里的二叉树可以用来搜索,也可以用来进行插入,删除等操作,拥有实际的意义。所以对于普通二叉树,我们不用学习他的增删查改,只用学习他的遍历等操作,并且复习一下递归的相关知识。

一.二叉树的理解:

我们先回顾一下回顾下二叉树的概念,二叉树是:

  1. 空树
  2. 非空:根节点,根节点的左子树、根节点的右子树组成的。

  对于一颗二叉树,我们看到它就要把他分为:根,左子树,右子树。对于左子树,在把他分为:根,左子树,右子树。对于右子树,在把他分为:根,左子树,右子树……以此类推直到左右子树都为空才停止。
在这里插入图片描述
  从概念中可以看出,二叉树定义是递归式的,因此后序基本操作中基本都是按照该概念实现的。

二.二叉树的遍历:

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

  按照规则,二叉树的遍历有:前序/中序/后序递归结构遍历。我们以这颗二叉树为例:
在这里插入图片描述

创建二叉树:

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

BTNode* BuyNode(BTDataType x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("malloc::fail");
		return;
	}

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

	return node;
}


BTNode* CreatTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);
	BTNode* node7 = BuyNode(7);


	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	node3->right = node7;


	return node1;
}

在这里插入图片描述

1.前序遍历:

  前序遍历的顺序是:根,左子树,右子树

在这里插入图片描述
代码实现:

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

结果:
在这里插入图片描述
在这里插入图片描述

2.中序遍历:

  中序遍历的顺序是:左子树,根,右子树
在这里插入图片描述
在这里插入图片描述
代码实现:

void InOrder(BTNode* root)
{

	if (root == NULL)
	{
		printf("NULL ");
		return;
	}
	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}

结果:
在这里插入图片描述

3.后序遍历:

  后序遍历的顺序是:左子树,右子树,根
在这里插入图片描述
代码实现:

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

结果:
在这里插入图片描述
  其实上面的三种遍历就是通过s三句代码的顺序导致结果的不同,当然他们的递归过程都能用下面这张图来代表:
在这里插入图片描述

4.层序遍历:

  除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下自左至右逐层访问树的结点的过程就是层序遍历

在这里插入图片描述
  那么如何实现层序遍历呢?这里我们就要用到我们之前所学的队列了!
  在这里,我们将二叉树的根先进队列,然后将其出队列,每出一次,就让其左右子结点进入队列,随后在出一个队列,将其左右子节点加入队列……这样通过队列的push和pop就能实现层序遍历

在这里插入图片描述

我们首先将队列的代码导入即可,就可以创建队列了:
在这里插入图片描述
代码实现:

void LevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
	{
		QueuePush(&q, root);
	}
	
	while (!QueueEmpty(&q))
	{
		BTNode* front= QueueFront(&q);
		QueuePop(&q);
		printf("%d ", front->data);
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}
	}
	QueueDestroy(&q);
}

注意:
  这里我们放入队列的不是要打印的数据,而是树结点的指针,为什么呢?如果我们存入的是要打印的数据(整形数据),那么我们无法找到他们的子节点!所以我们每次pop出一个指针,然后push这个指针(结点)的子节点即可。图解如下:
在这里插入图片描述

三.判断二叉树是否为完全二叉树:

我们先来看看这张图:
在这里插入图片描述
  我们会发现,通过层序遍历的方法,满二叉树在层序遍历时的非空结点一定是连续的空结点也是连续的,所以我们只要在层序遍历的基础上把空结点存入,然后判断空结点是否连续即可。

代码实现:

// 判断二叉树是否是完全二叉树
bool TreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		if (front == NULL)
		{
			break;
		}
		else
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
	}

	// 判断是不是完全二叉树
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		// 后面有非空,说明非空节点不是完全连续
		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}

四.二叉树结点数量:

  如果我们要计算结点的数量,通过上面所学的遍历的方式当然可以计算出结点数量。
在这里插入图片描述
这就是遍历的方法,但是事实上我们用分治的方法更多一些:

分治和遍历的区别:

拿学校人口统计作为例子,遍历法与分治法的区别如下:

遍历法,做法如下:
校长自己一个人带着一个本子,跑遍全校查人数

分治法,做法如下:
校长想知道人数,就找来院长统计每个院的人数相加,院长找来系主任统计每个系的人数相加……这样校长就不用亲自动手了。其实递归就是把任务交给打工人(呜呜)。
在这里插入图片描述
那么我们如何实现分治法呢?
总体思路就是 返回:左子树数量+右子树数量+1
代码实现:

int TreeSize(BTNode* root)
{
	return root == NULL ? 0 : 
	TreeSize(root->left) 
	+ TreeSize(root->right) + 1;
}

五.二叉树的高度(深度):

在这里要求二叉树的高度,我们也是用分治的思想:

int TreeHeight(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int leftHeight = TreeHeight(root->left);
	int rightHeight = TreeHeight(root->right);

	return leftHeight > rightHeight ? leftHeight+1 : rightHeight+1;
}

其实对于递归内容,我们只需要考虑:

  • 将问题分为子问题,子问题的解决方式和总问题的解决方式的方式一样
  • 有中止的条件

六.二叉树第k层节点个数

现在我们把他分为子问题:

当前树的第k层个数=左子树的第k-1层个数+右子树的第k-1层个数
代码如下:

int TreeKLevel(BTNode* root, int k)
{
	if (root == NULL)
	{
		return 0;
	}
	if (k == 1)
	{
		return 1;
	}
	int leftklevel = TreeKLevel(root->left, k - 1);
	int rightklevel = TreeKLevel(root->right, k - 1);

	return leftklevel + rightklevel;
}

总结

  更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

专栏订阅:
每日一题
c语言学习
算法
智力题
初阶数据结构
更新不易,辛苦各位小伙伴们动动小手,👍三连走一走💕💕 ~ ~ ~ 你们真的对我很重要!最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!

在这里插入图片描述

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

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

相关文章

【Linux】CentOS7.6 升级 gcc/g++

CentOS 7.6 升级 gcc/g的方法,不一定适用于其他linux系统 1.查看版本 g -v gcc -v当前查看版本,发现是4.8.5,这已经是2015年的旧版本了,对c11的支持不是很完善,为了方便学习和编写新版本的代码,升级一下还…

使用python采集分享119个PHP江湖论坛源码,总有一款适合您

分享119个PHP江湖论坛源码,总有一款适合您 119个PHP江湖论坛源码下载链接:https://pan.baidu.com/s/1Zz-GiS6WT3i16dZMz-5rvQ?pwdr416 提取码:r416 Python采集代码下载链接:采集代码.zip - 蓝奏云 我的博客地址:…

【Unity URP】探讨描边方案 自定义后处理Volume

写在前面 本篇内容实现了在URP下获取深度、法线实现描边的后处理描边之前做的工作,包括讨论描边方案,以及写shader之前的自定义renderFeature和Volume组件的过程。 由于是想复刻《SCHiM》游戏里的画面风格,所以本篇文章的需求很明确&#x…

国网B接口调阅实时视频规范解读和代码示例分析

接口描述 国网B接口调阅实时视频,相关规范写的比较粗略: 调阅实时视频包括信令接口和媒体流接口,采用标准的SIP INVITESDP流程,媒体传输使用RTP/RTCP。 SDP 中 RTP Payload 的取值应遵守下面接口参数中的定义: a&a…

用低代码平台可视化设计表单

表单在前端可谓是非常常见的场景,而且通常需要花费开发非常多的时间来处理各种复杂的逻辑。特别是在企业中后台的业务中,存在着大量的表单,比如客户的订单,投诉的问题单,服务跟进过程每个流程的流转。凡是存在用户输入…

西安五日游规划

文章目录前言一、行前准备二、必带清单三、打卡美食四、景点地理坐标五、旅游时间轴六、景点小巴士第一天第二天第三天第四天第五天其他七、住宿八、小贴士总结前言 西安五日游。计划从北京出发,游玩五天,第五天回京。 一、行前准备 计划行程 票务预订 …

雅思资料汇总

关于雅思 流程: 雅思考试将全面启用现场照相和生物识别技术, 包括指纹采集和验证,考生将无需提供个人照片。我们建议考生在考试当天提前到场以完成个人物品放置,身份证件验证,检录入场等一系列重要考前准备工作。大厅在当天会贴出考生的考号…

【网络原理】应用层协议 与 传输层协议

✨个人主页:bit me👇 ✨当前专栏:Java EE初阶👇 目 录🏉一. 应用层协议⚾️二. 传输层协议👒1. UDP 协议🌂2. 校验和👓3. TCP 协议🏉一. 应用层协议 我们自己写的应用程…

2023年MathorCup数模B题赛题

B 题 城市轨道交通列车时刻表优化问题 列车时刻表优化问题是轨道交通领域行车组织方式的经典问题之一。 列车时刻表规定了列车在每个车站的到达和出发(或通过)时刻,其在实 际运用过程中,通常用列车运行图来表示。图 1 为某一运行图的示例,图 …

代码随想录算法训练营第五十九天 | 503. 下一个更大元素 II、42. 接雨水

503. 下一个更大元素 II 方法一&#xff1a;将两个nums数组放在一起&#xff0c;使用单调栈求下一个更大元素&#xff0c;最后再把结果集即result数组resize到原数组大小就可以了。 方法二&#xff1a;在遍历的过程中模拟走了两遍nums class Solution { public:vector<in…

5G-OAI关于物理层中PDCCH源码解析

5G物理层是指5G网络的传输技术&#xff0c;包括无线帧、子帧、时隙、符号等方面的定义和规范。具体来说&#xff0c;5G物理层定义了无线帧的长度、帧结构、子帧结构、传输速率、带宽、时间同步等方面的参数&#xff0c;以及物理层信道的编码、调制和解调方式等方面的规范。5G物…

k8s 滚动部署学习总结

k8s 滚动部署学习总结 滚动发布 滚动发布配置总结 定义&#xff1a; 滚动升级&#xff08;Rolling update&#xff09; 就是指每次更新部分Pod&#xff0c;而不是在同一时刻将该Service下面的所有Pod shutdown&#xff0c;然后去更新逐个更新可以避免将业务中断 使用Deploy…

GEE初学者笔记之快速上手篇

1.基础概念 (1)谷歌云平台 整个GEE是基于Google Cloud云平台的一整套API开发环境。因此整个数据的处理全部都是在Google Cloud平台上实现的&#xff0c;无需本地机器参与运算。一般开发流程是在线/离线编辑代码&#xff0c;然后提交服务器端运行&#xff0c;完成之后会输出给我…

【Jenkins 2.x 实践指南】1.4 软件工程生产力--章节小结

目录 一、生产力三要素 1. 生产力 2. IT 中的生产力 二、Devops 和 Jenkins 1. DevOps 模式定义(AWS官方定义) 2. DevOps 实践经验 2.1 持续集成 2.2 持续交付 2.3 微服务 2.4 基础设施即代码 2.5 监控和日志记录 2.6 沟通与合作 一、生产力三要素 1. 生产力 劳动…

GPT系列简介与gpt训练(nanoGPT)

generateivelt pre-trained transformer ,GPT使用transformer做特征提取行&#xff0c;单项语言模型作为训练任务 gpt 1.0 通过自左向右生成式的构建预训练任务&#xff0c;然后得到一个通用的预训练模型&#xff0c;这个模型和BERT一样都可用来做下游任务的微调。GPT-1当时在…

Firefly-rk3288 开发板Linux系统编译

前言 手上的一块Firefly-RK3288开发板&#xff0c;看了下Firefly提供的SDK&#xff0c;压缩包就有15个多G&#xff0c;直接吓退。还好最近看到了韦东山老师提供的教学资料。记下学习步骤及遇到的问题解决办法。 1、开发环境 资料提供的有百问网制作的 ubuntu18.04 虚拟机镜像…

卷积计算转换为矩阵乘计算的几种场景和方法

本文默认卷积的输入输出数据格式为NHWC。 1x1卷积 输入shape为[N, H, W, C] , filter为[Hf, Wf, Ci, Co] FH, FW都为1&#xff0c;直接把输入shape reshape为[N, H * W, C], filter reshape为[[Hf * Wf * Ci, Co],然后进行矩阵乘得到[N, H * W, Co]&#xff0c;再reshape为卷…

ChatGPT 本地部署及搭建

这篇简要说下清华开源项目 ChatGLM 本地部署的详细教程。清华开源项目 ChatGLM-6B 已发布开源版本&#xff0c;这一项目可以直接部署在本地计算机上做测试&#xff0c;无需联网即可体验与 AI 聊天的乐趣。 项目地址&#xff1a;GitHub - THUDM/ChatGLM-6B: ChatGLM-6B&#xf…

一次小破站JS代码审计出XSS漏洞思路学习

今天看了小破站一个大佬的分析&#xff0c;感觉思路很有意思&#xff0c;感兴趣的xdm可以到大佬视频下提供的链接进行测试&#xff08;传送门&#xff09;这类社交平台的XSS漏洞利用起来其实危害是特别大的&#xff0c;利用XSS能在社交平台上呈现蠕虫式的扩散&#xff0c;大部分…

redis内存回收——过期、淘汰

DB结构删除策略惰性删除周期删除SLOWFAST淘汰策略redis内存设置过大时会增加同步等操作的复杂度 DB结构 /* Redis database representation. There are multiple databases identified* by integers from 0 (the default database) up to the max configured* database. The …