当前位置: 首页 > news >正文

【数据结构】二叉树的四种遍历方式——必做题

写在前面

学完上一篇文章的二叉树的遍历之后,来尝试下面的习题吧


开始做题

144. 二叉树的前序遍历 - 力扣(LeetCode)

94. 二叉树的中序遍历 - 力扣(LeetCode)

145. 二叉树的后序遍历 - 力扣(LeetCode)

为什么将这三道题放在一起呢?因为只要你学会了前序遍历,那么中序和后序遍历就自然不在话下(修改递归顺序),我就不写三个解析水字数了😅,一箭三雕,举一反三的时刻到了😁

敬告:先去做完,再看解析。为方便判错,力扣上的题加了很多限制,有些变量必要难以理解

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

题目简简单单就一句话,正是上一篇文章所讲的代码,但是参数却有些让人看不懂,我们通常这样写


void preorderTraversal(struct TreeNode* root) 
{if (root == NULL) return;  // 如果节点为空,返回printf("%d ", root->val);  // 先访问根节点preorderTraversal(root->left);  // 再递归遍历左子树preorderTraversal(root->right);  // 最后递归遍历右子树

但是力扣上的解析大都是这样的,为什么?

void PreOrder(struct TreeNode* root,int* arr,int* returnSize)
{if(root==NULL) return;arr[(*returnSize)++]=root->val;PreOrder(root->left,arr,returnSize);PreOrder(root->right,arr,returnSize);
}int* preorderTraversal(struct TreeNode* root, int* returnSize)
{int *arr=malloc(sizeof(int)*2000); //定义数组,用于存储遍历的返回值*returnSize=0;PreOrder(root,arr,returnSize);return arr;
}

原因:要求不同造成,需要更多参数;

  • 首先这道题不像上一篇文章我们写的那样,直接打印出来结点数值,而力扣要求将结点数值存进一个数组,返回时还得返回整个数组,这样我们就得先定义一个数组arr ,又因为需要malloc,故需要将数组定义成指针的形式;

  • 那returnSize的意思就是数组的长度,为什么要用指针呢?因为只有传值调用,指针接收,才能通过函数内returnSize的改变,进而影响returnSize被原本值,在这里初始值设为0就很巧妙,因为可以当成数组的下标;

  • 至于前序遍历在这里就可以必须要时刻更新这三个参数,干脆就直接再封装成一个函数来进行递归调用。

中序遍历和后序遍历就很简单了,一箭三雕,举一反三的时刻到了😁


102. 二叉树的层序遍历 - 力扣(LeetCode)

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

解析:这道题的难度有点大,耐心做

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     struct TreeNode *left;*     struct TreeNode *right;* };*//*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().*///用队列的顺序存储结构来实现,本身问题很简单,但上面的三条英文注释让整个题变得不简单起来
/*补充知识:二位动态整形数组的申请方法
int** arr=(int **)malloc(sizeof(int*)*3000);
arr[*returnSize] = (int*)malloc(sizeof(int) * (rear-front));
*/
int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes)
{*returnSize=0;  //数组大小设置为0if(root==NULL)  //根结点为空,没有遍历的必要,直接返回空return NULL;struct TreeNode *queue[3000];  //定义一个队列int **arr=(int**)malloc(sizeof(int*)*3000),front=0,rear=0;//定义一个二维数组*returnColumnSizes=(int*)malloc(sizeof(int)*3000);//根结点入队queue[rear++]=root;while(front!=rear)//这个是大循环{int temp=rear,k=0;arr[*returnSize] = (int*)malloc(sizeof(int) * (rear-front));while(front<temp)//rear会变化{struct TreeNode *p=queue[front++];//出队arr[*returnSize][k++] = p->val;if(p->left) //如果左结点不空,左节点入队{queue[rear++]=p->left;}if(p->right)  //如果右节点不空,右节点入队{queue[rear++]=p->right;}}(*returnColumnSizes)[*returnSize] = k;(*returnSize)++;}return arr;
}
  • 问:这段代码中returnSize和returnColumnSizes是什么意思?

  1. returnSize是一个指向整数的指针,用于存储二维数组arr的行数,即层序遍历结果的大小。在函数执行完毕后,通过修改returnSize来告知调用者结果的大小。

  1. returnColumnSizes是一个指向整数指针的指针,用于存储每一层中节点的数目。
    returnColumnSizes的指向的整数数组的大小应与arr的行数相同,即表示每一行中节点的数目。由于每一层的节点数目不同,因此我们需要动态分配一个整数数组来存储每一层中节点的数目。函数执行完毕后,returnColumnSizes指向的整数数组将包含每一层中节点的数目。

  1. 需要注意的是,如果函数中没有任何一层节点,那么returnSize将为0,而returnColumnSizes指向的数组应为NULL。

  • 问:为什么前者使用一级指针,后者使用二级指针?

  1. 在这段代码中,returnSize使用一级指针,而returnColumnSizes使用二级指针,是因为它们所表示的信息不同。

  1. returnSize指向的是整数类型的变量,用于表示层序遍历结果的行数,是一个单独的变量。因此,我们只需要通过一级指针将这个变量传递给函数,函数就可以修改这个变量的值,从而返回结果的行数。

  1. returnColumnSizes指向的是整数类型的指针数组,用于表示每一行中节点的数目,是一个数组。由于这个数组的大小在函数调用时未知,因此我们需要使用二级指针将它传递给函数。在函数内部,我们需要先分配一个整数类型的数组,然后将这个数组的地址存储到returnColumnSizes所指向的地址中。因此,我们需要使用二级指针。

  • int** arr=(int **)malloc(sizeof(int*)*3000);
    arr[*returnSize] = (int*)malloc(sizeof(int) * (rear-front));

  1. 第一行代码定义了一个名为arr的指向指针的指针变量,分配了一个大小为sizeof(int*)3000字节的内存,该内存用于存储二维数组的每个一维数组的地址

  1. 第二行代码则是为二维数组的一维数组分配内存,通过指针访问到第returnSize行,然后调用malloc函数分配一块大小为sizeof(int) * (rear-front)字节的内存,该内存用于存储一维数组中的元素,返回值为一维数组的首地址,使用强制类型转换将其转换为int类型,最后存储在arr[*returnSize]中,用于后续的访问。


写在最后

👍🏻 点赞,你的认可是我创作的动力!
收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!

相关文章:

【数据结构】二叉树的四种遍历方式——必做题

写在前面学完上一篇文章的二叉树的遍历之后&#xff0c;来尝试下面的习题吧开始做题144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09;94. 二叉树的中序遍历 - 力扣&#xff08;LeetCode&#xff09;145. 二叉树的后序遍历 - 力扣&#xff08;LeetCode&#xff09…...

Nginx使用“逻辑与”配置origin限制,修复CORS跨域漏洞

目录1.漏洞报告2.漏洞复现3.Nginx 修复3.1 添加请求头3.2 配置origin限制2.3 调整origin限制1.漏洞报告 漏洞名称&#xff1a; CORS 跨域漏洞等级&#xff1a; 中危漏洞证明&#xff1a; Origin从任何域名都可成功访问&#xff0c;未做任何限制。漏洞危害&#xff1a; 因为同源…...

Laravel框架02:路由与控制器

Laravel框架02&#xff1a;路由与控制器一、路由配置文件二、路由参数三、路由别名四、路由群组五、控制器概述六、控制器路由七、接收用户输入一、路由配置文件 以web网页路由文件为例&#xff1a; 默认根路由 路由定义格式Route::请求方式(请求的URL, 匿名函数或控制响应的方…...

【POJ 2418】Hardwood Species 题解(映射)

描述 阔叶树是一种植物群&#xff0c;具有宽阔的叶子&#xff0c;结出果实或坚果&#xff0c;通常在冬天休眠。 美国的温带气候造就了数百种阔叶树种的森林&#xff0c;这些树种具有某些生物特征。例如&#xff0c;虽然橡树、枫树和樱桃都是硬木树&#xff0c;但它们是不同的物…...

React组件之间的通信方式总结(下)

一、写一个时钟 用 react 写一个每秒都可以更新一次的时钟 import React from react import ReactDOM from react-domfunction tick() {let ele <h1>{ new Date().toLocaleTimeString() }</h1>// Objects are not valid as a React child (found: Sun Aug 04 20…...

【RabbitMQ笔记07】消息队列RabbitMQ七种模式之Publisher Confirms发布确认模式

这篇文章&#xff0c;主要接收消息队列RabbitMQ七种模式之Publisher Confirms发布确认模式。 目录 一、消息队列 1.1、发布确认模式 1.2、案例代码 &#xff08;1&#xff09;引入依赖 &#xff08;2&#xff09;编写生产者【消息确认--单条确认】 &#xff08;3&#xf…...

【华为OD机试模拟题】用 C++ 实现 - IPv4 地址转换成整数(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明IPv4 地址转换成整数题目输入输出示例一输入输出说明示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,...

闭包与高阶函数

文中内容均来自于曾探《JavaScript设计模式与开发实践》的学习笔记。闭包作用域变量的作用域&#xff0c;就是指变量的有效范围。局部变量、全局变量。变量的搜索是从内到外而非从外到内的。变量的生命周期对于全局变量莱索&#xff0c;全局变量的生命周期是永久的&#xff0c;…...

人工智能轨道交通行业周刊-第35期(2023.2.20-2.26)

本期关键词&#xff1a;重庆智慧轨道、智能运维主机、标准轨距、地方铁路公报、景深、机器视觉应用 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通Rai…...

快慢指针判断链表是否有环

快慢指针判断链表是否有环 单链表有可能存在环&#xff0c;有些情况下要判断一个单链表是否有环。数组的有个快慢指针的方法&#xff0c;其实单链表和数组有相似的地方&#xff0c;可以使用快慢指针的方法。具体做法如下&#xff1a; 首先创建两个指针&#xff0c;它们初始时…...

《MongoDB入门教程》第26篇 聚合统计之$max/$min表达式

本文将会介绍两个 MongoDB 表达式&#xff0c;返回一组数据中最大值的 $max 表达式&#xff0c;以及返回一组数据中最小值的 $min 表达式。 $max 表达式 $max 表达式用于返回一组数据中的最大值&#xff0c;语法如下&#xff1a; { $max: <expression> }$max 表达式在…...

FPGA纯verilog解码SDI视频 纯逻辑资源实现 提供2套工程源码和技术支持

目录1、前言2、硬件电路解析SDI摄像头Gv8601a单端转差GTX解串SDI解码VGA时序恢复YUV转RGB图像输出FDMA图像缓存HDMI输出3、工程1详解&#xff1a;无缓存输出4、工程2详解&#xff1a;缓存3帧输出5、上板调试验证并演示6、福利&#xff1a;工程代码的获取1、前言 FPGA实现SDI视…...

JVM篇之垃圾回收

一.如何判断对象可以回收 1.引用计数法 只要一个对象被其他变量所引用&#xff0c;就让它的计数加1&#xff0c;被引用了两次就让它的计数变成2&#xff0c;当这个变量的计数变成0时&#xff0c;就可以被垃圾回收&#xff1b; 弊端&#xff1a;当出现如下图的情况&#xff0…...

尝试用程序计算Π(3.141592653......)

文章目录1. π\piπ2. 用微积分来计算π\piπ2.1 原理2.2 代码2.3 结果2.4 分析1. π\piπ π\piπ的重要性或者地位不用多说&#xff0c;有时候还是很好奇&#xff0c;精确地π\piπ值是怎么计算出来的。研究π\piπ的精确计算应该是很多数学家计算机科学家努力的方向&#xf…...

【异常检测三件套】系列3--时序异常检测综述

写在前面: 异常检测共包含3个内容,从多个方面剖析异常检测方法,本文为第三篇。过往内容请查看以下链接: 【异常检测三件套】系列1--14种异常检测算法https://blog.csdn.net/allein_STR/article/details/128114175?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%…...

关于SAP 错误日志解析

有时候启动或操作sap会出现故障&#xff0c;只是察看sap用户当前目录下的日志文件可能不得要领&#xff0c;此时有必要察看work目录下的一些trace. 以Linux系统为例&#xff0c;其他的也差不多。 instance说明 如下 DVEBMGS?? ABAP Central Instance D?? …...

java:自定义变量加载到系统变量后替换shell模版并执行shell

这里的需求前提是&#xff0c;在项目中进行某些操作前&#xff0c;需要在命令后对shell配置文件的进行修改&#xff08;如ip、port&#xff09;&#xff0c;这个对于用户是不友好的&#xff0c;需要改为用户页面输入ip、port&#xff0c;后台自动去操作修改配置&#xff1b;那么…...

Redis高级删除策略与数据淘汰

第二章&#xff1a;Redis高级 学习目标 目标1&#xff1a;能够说出redis中的数据删除策与略淘汰策略 目标2&#xff1a;能够说出主从复制的概念&#xff0c;工作流程以及场景问题及解决方案 目标3&#xff1a;能够说出哨兵的作用以及工作原理&#xff0c;以及如何启用哨兵 …...

社畜大学生的Python之pandas学习笔记,保姆入门级教学

接上期&#xff0c;上篇介绍了 NumPy&#xff0c;本篇介绍 pandas。 目录 pandas 入门pandas 的数据结构介绍基本功能汇总和计算描述统计处理缺失数据层次化索引 pandas 入门 Pandas 是基于 Numpy 构建的&#xff0c;让以 NumPy 为中心的应用变的更加简单。 Pandas是基于Numpy…...

20_FreeRTOS低功耗模式

目录 低功耗模式简介 STM32低功耗模式 Tickless模式详解 Tickless模式相关配置 实验源码 低功耗模式简介 很多应用场合对于功耗的要求很严格,比如可穿戴低功耗产品、物联网低功耗产品等。 一般MCU都有相应的低功耗模式,裸机开发时可以使用MCU的低功耗模式。 FreeRTOS也…...

后进先出(LIFO)详解

LIFO 是 Last In, First Out 的缩写&#xff0c;中文译为后进先出。这是一种数据结构的工作原则&#xff0c;类似于一摞盘子或一叠书本&#xff1a; 最后放进去的元素最先出来 -想象往筒状容器里放盘子&#xff1a; &#xff08;1&#xff09;你放进的最后一个盘子&#xff08…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析

Linux 内存管理实战精讲&#xff1a;核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用&#xff0c;还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

云安全与网络安全:核心区别与协同作用解析

在数字化转型的浪潮中&#xff0c;云安全与网络安全作为信息安全的两大支柱&#xff0c;常被混淆但本质不同。本文将从概念、责任分工、技术手段、威胁类型等维度深入解析两者的差异&#xff0c;并探讨它们的协同作用。 一、核心区别 定义与范围 网络安全&#xff1a;聚焦于保…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...