【数据结构】二叉树的层序遍历(四)
目录
一,层序遍历概念
二,层序遍历的实现
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语言来实现的话因为没有队列的库,实现起来特别的繁琐,不过好理解,本身并不难,这就是层序遍历的实现;
第四阶段带大家了实现了层序遍历,后序会带大家刷一会经典题目来进行巩固;
后面博主会陆续更新;
如有不足之处欢迎来补充交流!
完结。
相关文章:

【数据结构】二叉树的层序遍历(四)
目录 一,层序遍历概念 二,层序遍历的实现 1,层序遍历的实现思路 2,创建队列 Queue.h Queue.c 3,创建二叉树 BTree.h BTree.c 4,层序遍历的实现 一,层序遍历概念 层序遍历:除了先序…...

macOS文件差异比较最佳工具:Beyond Compare 4
Beyond Compare for mac是一款Scooter Software研发的文件同步对比工具。你可以选择针对多字节的文本、文件夹、源代码,甚至是支持比对adobe文件、pdf文件或是整个驱动器,检查其文件大小、名称、日期等信息。你也可以选择使用Beyond Compare合并两个不同…...

Windows+Pycharm 如何创建虚拟环境
当我们开发一个别人的项目的时候,因为项目里有很多特有的包,比如 Pyqt5.我们不想破坏电脑上原来的包版本,这个时候,新建一个虚拟环境,专门针对这个项目就很有必要了. 简略步骤: 1.新建虚拟环境 1.打开 pycharm 终端(Terminal)安装虚拟环境工具: pip install virtualenv2.创…...

vant 按需导入 vue2
vant 按需导入 vue2 1、通过npm安装 # Vue 3 项目,安装最新版 Vant: npm i vant -S# Vue 2 项目,安装 Vant 2: npm i vantlatest-v2 -S2、自动按需引入组件 babel-plugin-import 是一款 babel 插件,它会在编译过程中…...
Java手写分治算法和分治算法应用拓展案例
Java手写分治算法和分治算法应用拓展案例 1. 算法思维导图 以下是用Mermanid代码表示的分治算法的实现原理: #mermaid-svg-nvJwIm97kPHEXQOR {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-nvJwIm97kP…...
学习 CodeWhisperer 的一些总结
目前一些常见的的 AI 工具 GitHub Copilot:GitHub 与 OpenAI 合作开发的一个人工智能助手。 Codeium:是一个免费的人工智能驱动的代码生成工具 Tabnine:一个自动代码生成工具,免费版本非常有限,只提供简短的代码完成…...

JavaScript 中的 `this` 指向问题与其在加密中的应用
JS中的 this 关键字是一个非常重要的概念,它在不同情况下会指向不同的对象或值。在本文中,我们将深入探讨 JavaScript 中 this 的各种情况,并思考如何将其应用于 JS加密中的一些有趣用途。 1. 全局上下文中的 this 在全局上下文中ÿ…...

深入理解算法的时间复杂度
文章目录 时间复杂度的定义时间复杂度的分类时间复杂度分析常见数据结构和算法的时间复杂度常见数据结构常见算法 常见排序算法说明冒泡排序(Bubble Sort)快速排序(Quick Sort)归并排序(Merge Sort)堆排序(Heap Sort) 时间复杂度的定义 时间复杂度就是一种用来描述算法在输入规…...

2023年度教育部人文社会科学研究一般项目评审结果,已公布!
【SciencePub学术】 9月15日,教育部社科司公示了2023年度教育部人文社会科学研究一般项目评审结果,共3482项。 其中,规划基金、青年基金、自筹经费项目共3029项通过专家评审;西部和边疆地区项目200项,新疆项目20项&a…...

十一、MySql的事务(上)
文章目录 一、引入(一)CURD不加控制,会有什么问题?(二)CURD满足什么属性,能解决上述问题? 二、什么是事务?三、事务的特性(一)原子性:…...
时间序列分析1--生成和导出时间序列数据
时间序列数据的生成 直接录入 1.行录入 ts.(price,startc(2015,1),frequency 12) # price为时间序列变量,start为起始读入时间 frequncy指定每年读入的数据的频率,frequncy4为季度数据、frequncy52为星期数据 2.列录入 scan() 1:101 ....6:7 7:…...

HarmonyOS应用开发—资源分类与访问
应用开发过程中,经常需要用到颜色、字体、间距、图片等资源,在不同的设备或配置中,这些资源的值可能不同。 应用资源:借助资源文件能力,开发者在应用中自定义资源,自行管理这些资源在不同的设备或配置中的表…...

C++中的转换构造函数
在 C/C++ 中,不同的数据类型之间可以相互转换。无需用户指明如何转换的称为自动类型转换(隐式类型转换),需要用户显式地指明如何转换的称为强制类型转换。 自动类型转换示例: int a = 6;a = 7.5 + a; 编译器对 7.5 是作为 double 类型处理的,在求解表达式时,先将 a 转换…...

JSP ssm 特殊人群防走失系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计
一、源码特点 JSP ssm 特殊人群防走失系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源 代码和数据库,系统主要…...

怎么实现一个登录时需要输入验证码的功能
今天给项目换了一个登录页面,而这个登录页面设计了验证码,于是想着把这个验证码功能实现一下吧。 这篇文章就如何实现登录时的验证码的验证功能结合代码进行详细地介绍,以及介绍功能实现的思路。 目录 页面效果 实现思路 生成验证码的控制…...
在android工程中新建Android模块报错
复制了复制正常的build.gradle文件,然后把theme里面的东西改成了下面这个样就好了 <resources xmlns:tools"http://schemas.android.com/tools"><!-- Base application theme. --><style name"Theme.JiQuan" parent"Theme…...

电脑桌面的复选框如何取消
电脑桌面图标的复选框如何取消 1. 概述2. 去掉图标的复选框方法结束语 1. 概述 当你拿到新的电脑开机后,发现桌面上软件应用的图标左上角有个小框,每次点击图标都会显示,并且点击图标时,小框还会打上√; 这个小框的…...

【Unity每日一记】资源加载相关和检测相关
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:uni…...

【数据结构】长篇详解堆,堆的向上/向下调整算法,堆排序及TopK问题
文章目录 堆的概念性质图解 向上调整算法算法分析代码整体实现 向下调整算法算法分析整体代码实现 堆的接口实现初始化堆销毁堆插入元素删除元素打印元素判断是否为空取首元素实现堆 堆排序创建堆调整堆整合步骤 TopK问题 堆的概念 堆就是将一组数据所有元素按完全二叉树的顺序…...

DAQ高频量化平台:引领Ai高频量化交易模式变革
近年来,数字货币投资市场掀起了一股热潮,以(BTC)为代表的区块链技术带来了巨大的商业变革。数字资产的特点,如无国界、无阶级、无门槛、高流动性和高透明度,吸引了越来越多的人们的关注和认可,创…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!
【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...