【算法专题训练】29、树的深度优先遍历

【信息科学与工程学】【物理/化学科学和工程技术】知识体系87——声学基础02 应用声学 编号类型领域问题问题的数学分析参数列表及常量/常数及参数的数值范围关联知识1技术应用应用声学如何利用超声波反射测量距离?设发射脉冲与接收回波的时间差为 Δt,声速为 c,则目标距离 d = c·Δt / 2。c ≈ 340 m/s (空气中,20°C);Δt 通常为 0.1 ms ~ 100 ms;d 对应范围约 0.017 m ~ 17 m。声波传播、反射定律、压电换能器、时延估计2现象分析应用声学为什么在音乐厅中某些位置听到的声音更清晰?声压级叠加:总声压级 Lp = 10 log₁₀(Σ 10^(Lp 阅读详情

1、树的基础知识

  • 二叉树中每个节点最多只有两个子节点,分别称为左子节点和右子节点。
  • 二叉树的根节点没有父节点,一棵非空二叉树只有一个父节点
  • 二叉树的叶子节点没有子节点

二叉树节点数据类型:

struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
}

2、中序遍历

  • 中序遍历的顺序,是先遍历二叉树的左子树,然后遍历二叉树的根节点,最后遍历二叉树的右子树。
  • 中序遍历是相对于根节点来说的,中序是说根节点在中间顺序遍历,相对于他的左右子树来说。
    代码实现方式有两种,递归与迭代实现方式

递归代码实现:

void inorderTraversal1(TreeNode *node)
{
  if (node == nullptr)
  {
    return;
  }
  inorderTraversal1(node->left);
  std::cout << node->val << " ," << std::endl;
  inorderTraversal1(node->right);
}

迭代代码实现

  • 中序遍历:迭代法
  • 使用栈保存遍历的结点,从根节点开始遍历
  • 遍历顺序为先遍历左子树,接着遍历根节点,最后遍历右子树
  • 所以如果有有左子树节点,则需要不断遍历其左子节点,并放到栈中保存
    • 当遍历到最左侧的叶子结点时,已经没有左子结点,则需要遍历当前根节点,对栈顶元素出栈
  • 此时,对于这棵子树来说,已经遍历完了左子树和根节点,接下来需要遍历右子树了,所以当前遍历根节点转换到右子节点上来
  • 如果右子节点为空,则继续从栈中取出栈顶元素来处理,
  • 所以要实现不断遍历到最左侧的左子结点,需要使用while循环不断遍历到做左子结点并保存到栈中
  • 如何左子结点遍历到叶子结点,则遍历当前的根节点,接着遍历他的右子节点,
  • 如果右子节点为空,则从栈中取出之前遍历的左子节点,他是更上一层的父节点
  • 如果右子节点和栈都为空了,则说明整棵树都遍历完了。
void inorderTraversal2(TreeNode *node)
{
  std::stack<TreeNode *> stack;
  TreeNode *curr = node;
  while (curr != nullptr || !stack.empty())
  {
    while (curr != nullptr) // 不断深入遍历左子节点,知道最左侧的叶子结点
    {
      stack.push(curr);
      curr = curr->left;
    }

    // 当前curr为叶子结点的左子节点,为空,需要从栈中取出栈顶元素来遍历
    curr = stack.top();
    stack.pop();
    // 打印
    std::cout << curr->val << " ," << std::endl;
    /**
     * 遍历他的右子节点
     * - 如果右子节点不为空,则以右子节点为根节点,继续遍历他的左子结点
     * - 如果右子节点为空,则当前这棵子树遍历完了,需要从栈中取出他对应的父节点进行遍历
     */
    curr = curr->right;
  }
}

3、前序遍历

  • 前序遍历:先遍历根节点,再遍历左子树,最后是右子树

递归代码实现:

void preorderTraversal1(TreeNode *node)
{
  if (node == nullptr)
  {
    return;
  }
  std::cout << node->val << " ," << std::endl;
  preorderTraversal1(node->left);
  preorderTraversal1(node->right);
}

迭代代码实现:

  • 前序遍历:迭代实现
  • 使用栈保存遍历到的结点数据,先遍历根节点,再遍历左子树,最后遍历右子树
void preorderTraversal2(TreeNode *node)
{
  std::stack<TreeNode *> stack;
  while (node != nullptr || !stack.empty())
  {
    // 节点不为空,则不断获取他的左子节点,并放入到栈中
    while (node != nullptr)
    {
      std::cout << node->val << " ," << std::endl;
      stack.push(node);
      node = node->left;
    }

    /**
     * 当左子树都遍历完了(node为空),则取出栈中的元素(一定有数据),
     * 栈顶元素为当前node节点的父节点,取出来遍历他的右子树
     */
    TreeNode *topNode = stack.top();
    stack.pop();
    node = topNode->right;
  }
}

4、后续遍历

  • 后序遍历:
  • 先遍历左子树,再遍历右子树,最后是根节点

递归代码实现:

void postorderTraversal1(TreeNode *node)
{
  if (node == nullptr)
  {
    return;
  }
  postorderTraversal1(node->left);
  postorderTraversal1(node->right);
  std::cout << node->val << " ," << std::endl;
}

迭代代码实现:

  • 后续遍历:迭代实现
  • 后续遍历的顺序是,先遍历左子树,接着遍历右子树,最后才是根节点
  • 同样先使用while循环不断遍历左子节点,并将遍历到的结点放到栈中
  • 当遍历到左侧的叶子结点时,取出栈顶节点,但是该结点现在还不做出栈操作,而是先判断他的右子节点之前是否遍历过
  • 如果之前没有遍历过,则继续以他的右子节点为根节点进行遍历,如果之前遍历过,则遍历遍历当前结点,并且栈顶元素出栈
  • 此时说明这棵左子树全部遍历完成,需要将curr的遍历结点设置为空,以便从栈中取出他的父节点,继续遍历他的右子树
    • 现在的问题是如何判断他的右子节点之前是否遍历过,通过设置一个prev属性,继续当前遍历的结点
void postorderTraversal2(TreeNode *node)
{
  std::stack<TreeNode *> stack;
  TreeNode *curr = node;
  TreeNode *prev = nullptr;
  while (curr != nullptr || !stack.empty())
  {
    // 不断遍历查找他的左子节点
    while (curr != nullptr)
    {
      stack.push(curr);
      curr = curr->left;
    }

    // 左子树遍历完了,需要从获取出栈顶元素
    TreeNode *topNode = stack.top();
    // 判断之前是否遍历过他的右子节点,有左子节点,且之前没有遍历过-》继续遍历他的左子节点
    if (topNode->right != nullptr && prev != topNode->right)
    {
      curr = topNode->right;
    }
    else
    {
      // 出栈,
      stack.pop();
      std::cout << topNode->val << " ," << std::endl;
      prev = topNode;
      curr = nullptr; // 设置为空,让下一步从栈中取出父节点进行遍历
    }
  }
}

5、总结

  • 树的深度优先遍历
  • 一棵二叉树,可以继续分为根节点和左子树与右子树,所以一共有三种深度优先遍历顺序,分别是前序遍历,中序遍历和后续遍历,这三种遍历顺序都是相对于根节点来表示的。
  • 树的深度优先遍历的递归实现方式,代码简单,就是有点太抽象了
  • 转换成迭代方式,使用栈数据结构来保存遍历的结点,更易于理解,树的深度优先遍历,都是先找到他的最左侧子节点,所以需要通过while循环不断遍历树的左子结点并放入到栈中保存。而后再从栈中取出来使用。
【信息科学与工程学】计算机科学与自动化——第一百五十五篇 缓存系统设计02 编号176-190共15个条目,覆盖了缓存互连网络(环形/交叉开关)、硅光互连、散热设计、3D封装TSV、信号完整性、冗余设计、老化补偿、电磁兼容、时钟分布、JTAG测试、安全硬件、调试探针、容错路由、体偏置、共振时钟。:编号161-175共15个条目,聚焦于缓存硬件设计与配置,涵盖了MESI协议、多级TLB、分支预测BTB/BHT、自适应预取引擎、ECC纠错汉明码、路分区硬件、非暂时性存储旁路、缓存冲刷指令、缓存锁定、压缩硬件、嗅探过滤器、虚拟化EPT、QoS限速、内置自测BIST、电源管理DVFS。 阅读详情

相关推荐

51单片机也能玩转信号发生器?手把手教你用DAC0832和LM358输出四种标准波形

本文详细介绍了如何使用51单片机和DAC0832芯片搭配LM358运放,自制低成本信号发生器,实现正弦波、矩形波、三角波和锯齿波四种标准波形的输出。从硬件选型、电路设计到编程实现,手把手教你完成这一实用电子项目,总成本不到50元,适合电子爱好者和学生实践。

weixin_30530939的博客 551

数据结构——深度优先遍历

最小深度是从根节点到最近叶子节点的最短路径的长度。中序遍历(Inorder Traversal):先递归地访问左子树,然后访问根节点,最后递归地访问右子树。后序遍历(Postorder Traversal):先递归地访问左子树,然后递归地访问右子树,最后访问根节点。最大深度是从根节点到最远叶子节点的最长路径的长度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。输入:root = [3,9,20,null,null,15,7]最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

weixin_43945471的博客 3330

RK3588部署Zipformer模型问题总结

本文分享了在RK3588嵌入式设备上部署小米Zipformer语音识别模型时遇到的问题及解决方法。主要遇到两个问题:1)在rknn_model_zoo例程编译时出现静态库版本不兼容,通过重新编译kaldi-native-fbank库并修改链接路径解决;2)sherpa-onnx编译时提示缺少portaudio库,通过修改编译脚本启用相关宏定义后成功编译。最终成功在RK3588上运行Zipformer模型,测试结果显示该模型具有较好的识别效果和实时性(RTF=0.22),验证了其在边缘设备上的适用性。

pkyang2004的博客 2144

Acwing 846-树的重心

#include<bits/stdc++.h> using namespace std; const int N=1e5+10; int n; vector<int> G[N]; bool vis[N]; int ans=N; //以u为根的子树中点的数量 int dfs(int u) { vis[u]=true; int sum=1,res=0; for(auto i : G[u]) { if(!vis[i]) .

她与伞皆过客的博客 593

433MHz无线通信

基本概念 工作频率:433.92MHz 调制方式:ASK/OOK,FSK,GFSK 现有遥控与接收器方案中,多数使用ASK/OOK调试方式。ASK即“幅移键控”又称为“振幅键控”,也有称为“开关键控”(通断键控)的,所以又记作OOK(On-Off keyed)信号。ASK是一种相对简单的调制方式。幅移键控(ASK)相当于模拟信号中的调幅,不同的是与载频信号相乘的是二进制数码。幅移就是把频...

沧海孤叶的博客 5万+

UNITE真菌数据库使用避坑指南:从下载到注释的完整流程

本文提供了UNITE真菌数据库从下载到注释的完整实战指南。针对真菌ITS序列分析,重点解析了数据库版本选择、格式转换的常见陷阱,并详细介绍了如何训练优化的sklearn分类器以提升物种注释的精度和可靠性,帮助用户构建高效稳定的本地工作流。

weixin_29240343的博客 199

数据结构-树与深度优先遍历

 笔者在读书时,选择的专业是计算机科学,但和大家一样,在处理线性的问题时较为熟悉,但当自己在尝试理解树和图这种非线性结构时,就总无法深刻准确的理解,为此,也很苦恼很无奈,但也没有什么好的办法。这次趁着完成了《漫画算法》的阅读,再次总结一下关于书中树的内容,也许是几年的工作经历吧,让自己对于代码的编写和理解有了更多的体会,也了解到这种非线性结构的重要性。漫画算法这本书确实生动简洁,理解起来方便,大家对于数据结构感兴趣的,可以也买这本书读读,挺有意思的。图画的形式确实能增强理解性。 概念理解 树这种结构与链表不

不当初 3140

用Seurat和ComplexHeatmap绘制单细胞marker基因热图:从数据处理到可视化全流程

本文详细介绍了使用Seurat和ComplexHeatmap绘制单细胞marker基因热图的全流程,涵盖从数据处理、基因筛选、平均表达矩阵计算到高级可视化与注释添加。重点解析了如何利用ComplexHeatmap生成发表级热图,并整合热词信息,解决单细胞数据可视化中的常见问题,提升科研图表质量。

weixin_29048775的博客 529

树的深度优先遍历

树与树的深度遍历方法

weixin_55438199的博客 1997

国密GmSSL v2版本命令行方式生成国密sm2私钥、公钥、签名和验证签名

GmSSL是国密算法的工具库(主要包含SM2、SM3、SM4和国密SSL证书生成等功能),项目本身是OpenSSL的分支,但是截至文章发布为止,OpenSSL主分支的国密算法并不完善,目前并不支持签名和解签,所以国密算法这块还是需要使用GmSSL工具库。网上现在并没有v2版本的GmSSL可用的命令行文章,本章用于记录这些命令。本文原创自csdn博客,其他网站看到这篇文章都是盗,版,爬。虫。网站,支持原创,远离盗版。

eguid音视频方向博客,分享经过实践检验的硬核音视频技术。FFmpeg、openCV和JavaCV音视频和图像处理系列教程发布十周年,众多开发者的严格验证。欢迎关注,一起交流探索学习最新音视频和图像处理技术 4604

C++ int转四字节数组

字节转换

我不是码农的博客~~~ 973

算法总结-深度优先遍历和广度优先遍历

所以广度优先遍历也叫层序遍历,先遍历第一层(节点 1),再遍历第二层(节点 2,3,4),第三层(5,6,7,8),第四层(9,10)。(1)、我们从根节点1开始深度优先遍历,它相邻的节点有2、3、4,依先遍历节点2,再遍历2的右边节点5,再遍历9,至此便无可遍历的节点。对于每个节点来说,先遍历当前节点,然后把右节点压栈,再压左节点(这样弹栈的时候会先拿到左节点遍历,符合深度优先遍历要求)。广度优先遍历,指的是从图的一个未遍历的节点出发,先遍历这个节点的相邻节点,再依次遍历每个相邻节点的相邻节点。

hhhlizhao的博客 2万+

【vsomeip3 教程】SOME/IP中间件去抖策略全解析

本文探讨了在SOME/IP中间件中实现Debounce(去抖动)机制的必要性和实现原理。文章首先分析了中间件层进行Debounce的四大动机:多订阅者共享收益、语义显式化、协议噪声屏蔽和入口处背压控制。接着详细阐述了Debounce的底层原理,包括变化检测机制(ignore和mask的应用)、时间门控策略(interval的两种时间基准)以及超时补发机制,并通过表格清晰展示了不同参数组合的效果和适用场景。最后,文章提出了工程落地的具体方法,包括策略选型、ignore/mask的设计方法论以及分层验证调试的实

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 232

蓝桥杯国赛Python模拟题深度解析:从算法原理到实战避坑

动态规划和深度优先搜索是算法竞赛中的核心思想,动态规划通过定义状态与转移方程高效解决最优化问题,而深度优先搜索则系统性地枚举所有可能路径,是解决组合与路径问题的利器。掌握这些算法原理,能显著提升在数据结构应用、数学建模及代码优化方面的工程实践能力。在蓝桥杯等编程竞赛中,此类技术是攻克高难度题目的关键。本文以一份高仿真度的国赛级Python模拟题为载体,深入剖析了动态规划在路径规划问题中的状态定义与转移,以及深度优先搜索在排列组合问题中的回溯框架,为备赛者提供了从识别算法模型到代码实现的完整实战指南。

weixin_34050519的博客 460

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

决策树算法ID3、C4.5、CART:从信息增益到基尼系数的选型与实战

决策树是一种基于特征分裂的监督学习模型,其核心原理是通过信息熵、信息增益、增益率或基尼系数等指标选择最优分裂点,从而构建树结构。这些指标决定了模型对特征类型、缺失值处理及过拟合控制的适应性。在工程实践中,ID3、C4.5和CART分别适用于不同场景:ID3适合离散特征教学,C4.5支持连续特征和剪枝,CART则统一处理分类回归并具备高效剪枝。理解这些算法的计算逻辑与选型依据,能帮助开发者在特征工程、基线模型选择及面试中做出更优决策。

weixin_30861459的博客 335

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Python机器学习:从零基础到项目实战

当您翻开此书,您正踏入一场数据与智慧的修行。机器学习,并非冰冷的符码,而是机器模拟人类洞察世界的法门。本书将带您,以Python为舟,泛游于算法之海。我们不只传授“术”,更探求其后的“道”——从数据的生灭流转中观照规律,于模型的迭代演进里体悟得失。愿您合上书卷时,收获的不仅是驾驭数据的技能,更有一双洞悉复杂、化繁为简的“智慧之眼”。现在,让我们一同启程。

YunWisdom 968

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

KD树实现人群行为与地理空间的动态邻近分析

KD树是一种经典的多维空间索引数据结构,其核心原理是通过递归轴向分割构建平衡二叉树,并利用超平面距离剪枝实现高效K近邻搜索。在用户行为分析场景中,它能将地理坐标(经纬度)与人口统计特征(如年龄、教育、职业)融合为混合特征向量,以可计算的方式定义‘附近’与‘同类人群’,显著优于行政区划粗粒度切分或暴力遍历。该技术具备低延迟(毫秒级查询)、内存友好、Python生态成熟(scipy.spatial.cKDTree)等工程优势,广泛适用于本地生活选址、社区化精准营销、线下零售人群洞察等需要空间+属性双重约束的业务

weixin_34074740的博客 352

基础算法--树与图的深度优先遍历

从名字上的“深度优先”,我们很容易联想到深度优先搜索(DFS)。顾名思义,树与图的深度优先遍历与BFS,它们的核心思想究其根本都是递归。递归的自我做题感悟:1、递归到下一层的时候,灵活运用递归回来的时候前面的条件2、递归回溯的时候,递归之后的条件是返回给上一层的。

2202_75418863的博客 1343

【数据结构】二叉树的·深度优先遍历(前中后序遍历)and·广度优先(层序遍历)

二叉树的·深度优先遍历(前中后序遍历)and·广度优先(层序遍历)

luhaoran814的博客 3535

深度优先遍历(DFS)

深度优先遍历(,全称为),是我们树或者图这样的数据结构中常⽤的⼀种。这个算法会尽可能深的搜索树或者图的分⽀,直到⼀条路径上的所有节点都被遍历完毕,然后再回溯到上⼀层,继续找⼀条路遍历。以及。因为树的定义本⾝就是递归定义,因此采⽤递归的⽅法去实现树的三种遍历不仅容易理解⽽且代码很简洁。并且前中后序三种遍历的唯⼀区别就是,在做题的时候,选择⼀个适当的遍历顺序,对于算法的理解是⾮常有帮助的。

ijj_zZ的博客 2985

二叉树遍历(深度优先+广度优先)

二叉树的遍历分为两类,一类是深度优先遍历,一类是广度优先遍历。

Doublelv 的博客专栏。 1万+

数据结构与算法 | 树的深度优先遍历

# CY3761 | 2021-12-22 11:15 """ A BC(A) DE(B) FG(C) H(D) 树的深度优先遍历 先序遍历 根节点->左子树->右子树 从根开始 是否具有子树?是 遍历左节点.. 接着循环 是否具有子树,无 往上一层,是否具有右子树?是 遍历右节点.. 接着循环 假设如果E有子节点,则继续下层遍历左再往上遍历右 A->B->D->H->E->C->F->G 中序遍历 左子树->右子树->根节点

CY3761的博客 1233

数据结构--树存储结构 & 深度优先遍历 & 广度优先遍历 通俗易懂

树的概念 ​ 首先,树是一种常用的非线性数据结构,是以边(Edge)相连的节点(Node)的集合,每个节点存储对应的值,当存在子节点时与之相连。 根节点:是树的首个节点 边:所有节点都由边相连,用于标识节点间的关系 叶子结点:树的末端节点,它们没有子节点 树的高度:由根节点出发,到子节点的最长路径长度(从下往上) 树的深度:指对应节点到根节点路径长度(从上往下) 空树:如果树节点个数为零,那么构成的树成为空树 树的层:从一棵树的树根开始,树根所在层为第一层,树的孩子节点所在的层为第二层,以此类推。 节点

weixin_43710037的博客 3070

二叉树(一):深度优先遍历与广度优先遍历

二叉树是一种非常高效的数据结构,树结构可以高效地查找和搜索语义,比如近邻算法中就用到了树来存储训练数据,大大提高了近邻搜索的效率,又比如电脑的文件管理器,都采用了树结构,通过树查找会变得十分快捷。总之,二叉树这种数据结构的应用非常广泛,能够大大提高搜索效率,本文将全面讲解二叉树结构以及二叉树的相关算法,相信会对大家数据结构与算法的学习产生很大的帮助。...............

Mike_honor的博客 3337

【数据结构】多叉树的深度优先遍历DFS和广度优先遍历BFS(含C++递归和非递归方式实现)

本文主要讲解多叉树的遍历,并附有相关代码。

weixin_50941083的博客 6061

树的深度与广度优先遍历

树是前端工程师最经常打交道的一个数据结构,比如说html标签组成的dom树、树形控件等。 在js中没有树这个数据结构,但是可以用Object和Array来构建树: //val是当前的节点值,children是子节点 const tree = { val: 'A', children: [ { val: 'B', children: [ { val: 'D',

weixin_58855537的博客 4662
上一篇: 【算法专题训练】28、队列与二叉树层序遍历
下一篇: 【算法专题训练】30、二叉树的应用
Tim_10
博客等级 码龄2年 162粉丝 106原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值