【数据结构】二叉树的层序遍历(四)

news2024/10/7 20:34:26

 目录

一,层序遍历概念

二,层序遍历的实现

        1,层序遍历的实现思路

        2,创建队列

        Queue.h

        Queue.c

        3,创建二叉树

        BTree.h

        BTree.c

        4,层序遍历的实现


一,层序遍历概念

层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历;

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

二,层序遍历的实现

        1,层序遍历的实现思路

层序遍历:按照每一行从左到右对二叉树的各个结点进行访问

但是呢,对一层访问结束了该如何访问下一层呢?就拿上图举例,访问完(4)结点后该如何访问(3)结点呢?(4)结点中并没有(3)结点的信息;

算法思路:

可以借助一个队列,首先将二叉树的根结点入队,然后访问出队结点并出队,如果有左孩子结点,左孩子结点也入队;如果有右孩子结点,右孩子结点也入队。然后访问出队结点并出队,直到队列为空为止

过程演示: 

(1)入队列,访问队头结点(1),然后(1)出队列,此时(1)的左子树(2)右子树(4)相继入队列;此时队列: 头<---- (2)(4)    <---尾

访问队头结点(2),然后(2)出队列,此时(2)的左子树(3)入队列,此时队列:(4)(3)

访问队头结点(4),然后(4)出队列,此时(4)的左子树(5)右子树(6)相继入队列;

此时队列:(3)(5)(6)

访问队头结点(3),然后(3)出队列,因为(3)没有左右子树,此时没有数据入队列,此时队列:(5)(6)

访问头结点(5),然后(5)出队列,此时队列:(6)

访问头结点(6),然后(6)出队列,此时队列:NULL,结束!

下面是另一棵二叉树的遍历来帮助我们理解;

        2,创建队列

首先我们得创建一个队列,队列具体细节就不过多解释了,之前博客有专门的详细介绍过;

队列的性质:先进先出,也就是尾插,头删的单链表;

        Queue.h

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include"BTree.h"

typedef BTNode* QDataType;
//结点
typedef struct QListNode
{
	struct QListNode* next;
	QDataType data;
}QNode;

// 队列
typedef struct Queue
{
	QNode* front; // 队头
	QNode* rear; //队尾
	int size;
}Queue;

// 初始化队列 
void QueueInit(Queue* q);
// 队头入队列 
void QueuePush(Queue* q, QDataType data);
// 队尾出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 判空
int QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

        Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);
	q->front = q->rear = NULL;
	q->size = 0;
}

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->data = data;
	if (q->front /*= q->rear*/ == NULL)//谨记判断不要用此等格式
	{
		q->front = q->rear = newnode;
	}
	else
	{
		q->rear->next = newnode;
		q->rear = newnode;
	}
	q->size++;
}
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	if (q->front->next == NULL)
	{
		free(q->front);
		q->front = q->rear = NULL;
	}
	else
	{
		QNode* next = q->front->next;
		free(q->front);
		q->front = next;
	}
	q->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->front->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->rear->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);
	return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q)
{
	assert(q);
	return q->size == 0;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{
	assert(q);

	QNode* cur = q->front;
	QNode* next = NULL;
	while (cur)
	{
		next = cur->next;
		free(cur);
		cur = next;
	}
	cur = NULL;
	q->rear = NULL;
}

这队列已经构造完成了,我们还需要一棵二叉树;

        3,创建二叉树

二叉树之前我们也创建过,现在也不过多介绍了,直接上硬菜!

        BTree.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int BTDataType;
//二叉链
typedef struct BinaryTreeNode
{
	BTDataType data; // 当前结点值域	
	struct BinaryTreeNode* left; // 指向当前节点左孩子
	struct BinaryTreeNode* right; // 指向当前节点右孩子
}BTNode;

//动态创立新结点
BTNode* BuyNode(BTDataType x);
//创建二叉树
BTNode* GreatBTree();

        BTree.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"BTree.h"
#include"Queue.h"
//动态创立新结点
BTNode* BuyNode(BTDataType x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	assert(newnode);
	newnode->data = x;
	newnode->left = NULL;
	newnode->right = NULL;
	return newnode;
}

//创建二叉树
BTNode* GreatBTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);
	BTNode* node5 = BuyNode(5);
	BTNode* node6 = BuyNode(6);

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

	return node1;
}

这个队列和二叉树的 .c文件都要包含彼此的头文件,将他们链接起来;

        4,层序遍历的实现

按照之前的分析思路,以此构建代码;

//层序遍历
void LevelOrder(BTNode* root)
{
	Queue q;
	// 初始化队列 
	QueueInit(&q);
	// 队尾入队列 
	if (root)
	{
		QueuePush(&q, root);
	}
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q)->data);
		BTNode* cur = QueueFront(&q);
		// 队头出队列
		QueuePop(&q);
		if (cur->left)
		{
			QueuePush(&q, cur->left);
		}
		if (cur->right)
		{
			QueuePush(&q, cur->right);
		}
	}
}
int main()
{
	BTNode* root = GreatBTree();
	//层序遍历
	LevelOrder(root);
	return 0;
}

 确实是一层一层进行遍历的;

之前的遍历都是递归实习的,而层序遍历是循环实现的,目前用c语言来实现的话因为没有队列的库,实现起来特别的繁琐,不过好理解,本身并不难,这就是层序遍历的实现;

第四阶段带大家了实现了层序遍历,后序会带大家刷一会经典题目来进行巩固;

后面博主会陆续更新;

如有不足之处欢迎来补充交流!

完结。


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

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

相关文章

Day981.OAuth 2.0的工作流程与安全问题 -OAuth 2.0

OAuth 2.0的工作流程与安全问题 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于OAuth 2.0的工作流程与安全问题的内容。 一、OAuth 2.0 工作流程串讲 OAuth 2.0 是一种授权协议&#xff0c;这种协议可以让第三方软件代表用户去执行被允许的操作。 那么&#xff0c;…

HI_NAS linux 记录

dev/root 100% 占用解决记录 通过下面的命令查看各文件夹 大小 sudo du --max-depth1 -h # 统计当前文件夹下各个文件夹的大小显示为M 最终发现Var/log 占用很大空间 发现下面两个 log 占用空间很大&#xff0c;直接 rm-rf 即可 HI NAS python3 记录 # 安装pip3 sudo apt u…

4.后端·新建子模块与开发(传统模式)

文章目录 学习资料新建子模块与各层查询entity的列表entitymapper层service层controller层 测试 学习资料 https://www.bilibili.com/video/BV13g411Y7GS?p8&spm_id_frompageDriver&vd_sourceed09a620bf87401694f763818a31c91e b站的学习视频 新建子模块与各层 在r…

Angular变更检测机制

前段时间遇到这样一个 bug&#xff0c;通过一个 click 事件跳转到一个新页面&#xff0c;新页面迟迟不加载&#xff1b; 经过多次测试发现&#xff0c;将鼠标移入某个 tab &#xff0c;页面就加载出来了。 举个例子&#xff0c;页面内容无法加载&#xff0c;但是将鼠标移入下图…

NO.396 旋转数组

题目 给定一个长度为 n 的整数数组 nums 。 假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组&#xff0c;我们定义 nums 的 旋转函数 F 为&#xff1a; F(k) 0 * arrk[0] 1 * arrk[1] ... (n - 1) * arrk[n - 1] 返回 F(0), F(1), ..., F(n-1)中的最大值 。 生成…

深度学习-卷积神经网络-纹理表示卷积神经网络-卷积神经网络-[北邮鲁鹏]

这里写目录标题 参考文章全连接神经网络全连接神经网络的瓶颈全连接神经网络应用场景 卷积神经网络卷积层(CONV)卷积核卷积操作卷积层设计卷积步长(stride)边界填充特征响应图组尺寸计算 激活层池化层(POOL)池化操作定义池化操作作用池化层超参数常见池化操作 全连接层(FC)样本…

linux相关知识以及有关指令3

在linux的世界中我们首先要有万物皆文件的概念&#xff0c;那么在系统中有那么多的文件&#xff0c;我们该怎么区分呢&#xff1f;文章目录 1. 文件分类2. 文件的权限1). 拥有者和所属组以及other2). 文件的权限3). 粘滞位4). 对于权限修改的拓展知识点a.修改权限b.修改拥有者所…

智慧工地平台源码 劳务实名制、视频监控、扬尘监测、起重机械安全监测

伴随着技术的不断发展&#xff0c;信息化手段、移动技术、智能穿戴及工具在工程施工阶段的应用不断提升&#xff0c;智慧工地概念应运而生&#xff0c;智慧工地平台围绕施工现场管理&#xff0c;构建全方位的智能监控防范体系弥补传统方法和技术在监管中的缺陷&#xff0c;形成…

分享一个Python 写的监控日志log txt文档 的代码

监控log文件的需求 某些特殊原因&#xff0c;想一直看到.log 的最后一行打印&#xff0c;所以写了一些代码监控log &#xff08;有个奇怪需求&#xff0c;就是log 因为重复启动原因&#xff0c;会一直加&#xff0c;不是同一个log&#xff09; 监控界面 涉及的Python代码&…

管理类联考——数学——汇总篇——知识点突破——代数——数列——秒杀

&#x1f41f; ⛲️ 特殊值秒解数列 当数列题目中只有一个条件时&#xff0c;在不违背题意的条件下&#xff0c;可以直接利用特殊值&#xff0c; 令其公差为0或公比为1。 注意&#xff1a;一定要检验是否符合题意&#xff0c;题目中如果出现公差不为0或公比不为1&#xff0c;则…

华为云云耀云服务器L实例评测|部署前后端分离项目

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 学习测评 ✨特色专栏&#xff1a; MyS…

[NLP] LLM---<训练中文LLama2(一)>训练一个中文LLama2的步骤

一 数据集 【Awesome-Chinese-LLM中文数据集】 【awesome-instruction-dataset】【awesome-instruction-datasets】【LLaMA-Efficient-Tuning-数据集】Wiki中文百科&#xff08;25w词条&#xff09;wikipedia-cn-20230720-filteredBaiduBaiKe&#xff08;563w词条&#xff09; …

VIRTIO-SCSI代码分析(3)VIRTIO SCSI数据流处理

VIRTIO SCSI整体数据流如下&#xff1a; IO请求下发过程 虚拟机中通过FIO等下发IO请求&#xff0c;IO请求通过VFS/filesystem&#xff0c;BLOCK层&#xff0c;然后到SCSI层&#xff0c;传递给virtio-scsi驱动&#xff0c;virtio-scsi驱动通过virtioscsi_commit_rqs()下发IO请求…

利用 SOAR 加快事件响应并加强网络安全

随着攻击面的扩大和攻击变得越来越复杂&#xff0c;与网络攻击者的斗争重担落在了安全运营中心 &#xff08;SOC&#xff09; 身上。SOC 可以通过利用安全编排、自动化和响应 &#xff08;SOAR&#xff09; 平台来加强组织的安全态势。这一系列兼容的以安全为中心的软件可加快事…

【100天精通Python】Day63:Python可视化_Matplotlib绘制子图,子图网格布局属性设置等示例+代码

目录 1 基本子图绘制示例 2 子图网格布局 3 调整子图的尺寸 4 多行多列的子图布局 5 子图之间的共享轴 6 绘制多个子图类型 7 实战&#xff1a; 绘制一个大图&#xff0c;里面包含6个不同类别的子图&#xff0c;不均匀布局。 绘制子图&#xff08;subplots&#xff09;…

redis的安装、基础命令学习、常用数据结构

文章目录 前言一、Redis安装1.Ubuntu下安装&#xff08;1&#xff09;切换到root用户下&#xff08;2&#xff09;使用apt安装redis5&#xff08;3&#xff09;为了使redis支持远程连接&#xff0c;修改以下地方&#xff08;4&#xff09;验证安装是否成功 2.Centos7下安装&…

基于Java+SpringBoot+Vue+uniapp点餐小程序(包含协同过滤算法和会员系统,强烈推荐!)

校园点餐小程序 一、前言二、我的优势2.1 自己的网站2.2 自己的小程序&#xff08;小蔡coding&#xff09;2.3 有保障的售后2.4 福利 三、开发环境与技术3.1 MySQL数据库3.2 Vue前端技术3.3 Spring Boot框架3.4 微信小程序 四、功能设计4.1 系统功能结构设计4.2 主要功能描述 五…

理清Spring事务的核心关键类

在spring事务源码的内部&#xff0c;会有几个比较核心关键的类&#xff0c;虽然这基本上都是源码内部才使用到的类&#xff0c;但是有时候我们要对其做一些改造的时候免不了要去使用到这些类&#xff0c;并且这些类在spring事务内部都是起到关键的作用&#xff0c;对了解spring…

[2023-09-13]使用EXPDP/IMPDP迁移数据库后统计信息引起的性能问题

问题描述&#xff1a; 客户在使用expdp/impdp迁移数据库完成后&#xff0c;在新环境收集统计信息&#xff0c;但是在迁移完成的当天中午&#xff0c;好多SQL语句执行变慢&#xff0c;执行计划发生了改变&#xff0c;下面通过案例来说明。 1、准备数据 scott用户下创建test表&…

进程控制再学习

0.“开两个终端窗口” 因为学校用的虚拟机&#xff0c;得用终端登录&#xff0c;不能像shell一样直接复制窗口。 我们只需要登录两次就可以了&#xff08;方便监视&#xff09; 1.ps 1.循环ps while :;do ps -f;ps -ef|grep zombie;done 每秒打印一次&#xff1a; while :…