带你深入理解二叉树的遍历

简介: 带你深入理解二叉树的遍历

二叉树的遍历

1. 二叉树的前序、中序、后序遍历

  • 前、中、后序遍历又叫深度优先遍历
  • 注:严格来说,深度优先遍历是先访问当前节点再继续递归访问,因此,只有前序遍历是严格意义上的深度优先遍历
  • 首先需要知道下面几点:
  1. 任何一颗二叉树,都由根节点、左子树、右子树构成。

如图:

  1. 分治算法:分而治之。大问题分成类似的子问题,子问题再分成子问题……直到子问题不能再分割。对树也可以做类似的处理,对一棵树不断地分割,直到子树为空时,分割停止。
  2. 关于二叉树的许多问题我们都要利用分治思想,将一棵完整的树分解成根和左右两棵子树,然后再对这两棵子树进行相同的递归处理,最后得到结果。
  3. 如果对递归的过程想的不太清楚,建议画递归展开图来辅助理解

1.1 前序(先根)遍历

  • 遍历顺序:根- > 左子树 -> 右子树(即先访问根,再访问左子树,最后在访问右子树)
  • 如上图中:A -> B -> C -> NULL -> NULL -> D -> NULL -> NULL -> E -> NULL -> NULL
typedef char BTDataType;
typedef struct BinaryTreeNode
{
   struct BinaryTreeNode *left; //指向左子树
   struct BinaryTreeNode *right;  //指向右子树
    BTDataType data;
}BTNode;
void PrevOrder(BTNode * root) //前序遍历
{
   if (!root)
       return;
   printf("%d ",root->data);  //根
   PrevOrder(root->left);   //左子树
   PrevOrder(root->right);    //右子树
   return;
}

递归顺序图:

递归展开图:

1.2 中序(中根)遍历

  • 遍历顺序:左子树 -> 根 -> 右子树(即先访问左子树,再访问根,最后在访问右子树)
  • 如上图中:NULL -> C -> NULL -> B -> NULL -> D -> NULL -> A -> NULL -> E -> NULL
void InOrder(BTNode* root)
{
   if (!root)
    return;
   InOrder(root->left); //左子树
   printf("%c ", root->data);   //根
   InOrder(root->right);  //右子树
   return;
}

递归顺序图:

1.3 后序(后根)遍历

  • 遍历顺序:左子树 -> 右子树 -> 根(即先访问左子树,再访问左=右子树,最后在访问根)
  • 如上图中:NULL -> NULL -> C -> NULL -> NULL -> D -> B -> NULL -> NULL -> E -> A
void PostOrder(BTNode* root)
{
   if (!root)
   {
    printf("NULL ");
    return;
   }
   PostOrder(root->left); //左子树
   PostOrder(root->right);    //右子树
   printf("%c ", root->data);   //根
}

递归顺序图:


2. 二叉树的层序遍历

  • 层序遍历又叫广度优先遍历
  • 设二叉树的根节点所在层数为1,层序遍历就是从根节点出发,首先访问第一层的节点,然后从左到右访问第二层上的节点,接着访问第三层的节点,以此类推,自上而下,自左往右逐层访问树的结点的过程就是层序遍历
  • 层序遍历借助队列的先进先出思想来实现
  • 核心思想:上一层带下一层
  • 如图就是对上面那棵树的层序遍历示意图:

  • 实现代码
typedef BTNode* QDataType;    //队列元素类型
typedef struct QueueNode
{
   struct QueueNode* next;
   QDataType data;
}QueueNode;
typedef struct Queue  //定义存放指向队头,队尾指针的结构体
{
   QueueNode* head; //指向队头
   QueueNode* tail; //指向队尾
}Queue;
//层序遍历
void LevelOrder(BTNode* root)   
{
   Queue *q = (Queue *)malloc(sizeof(Queue)); //创建队列
   QueueInit(q);  //初始化队列
   //如果根节点为空,直接退出函数
   if (!root)
    return;
   QueuePush(q, root);    //先将根节点入队入队
   while (!QueueEmpty(q))   //当队列不为空
   {
    BTNode* front = QueueFront(q);    //接收队头元素
    QueuePop(q);    //出队头元素
    printf("%c ", front->data); //访问该节点
    if (front->left)    //如果左子树不为空
      QueuePush(q, front->left);      //左子树入队
    if (front->right)   //如果右子树不为空
      QueuePush(q, front->right);   //右子树入队
   }
   printf("\n");
   QueueDestroy(q);   //销毁队列  
}

3. 二叉树遍历的应用

  • 由二叉树和层序遍历的思想,我们可以构造出这棵树

  • 再有前序遍历 根- > 左子树 -> 右子树 的思想,可以知道,这棵树的前序序列为:A B D H E C F G

  • 这道题是由二叉树的前序序列和中序序列来确定二叉树,我们知道中序遍历的思想是 左子树 -> 根 -> 右子树 ,根将左子树和右子树分割开来,那么我们就可以先用前序序列确定根,再用中序序列确定根的左右子树,这样就可以将这棵二叉树确定了,如图:

  • 显然根节点为E

  • 这题和第二题类似,同样是先由后序遍历(左子树 -> 右子树 -> 根)确定根节点,再由中序遍历确定根的左右子树,只是用后序遍历确定根节点时要从最后开始。如图:

  • 易得前序遍历为a b c d e

总结

由于二叉树的中序遍历可以分割二叉树的左右节点,因此 前序序列 + 中序序列 / 后序序列 + 中序序列 都可以构建出一棵二叉树,而单独序列和 前序序列 + 后序序列就不行。

相关文章
|
JSON 数据格式 Python
Python json中一直搞不清的load、loads、dump、dumps、eval
Python json中一直搞不清的load、loads、dump、dumps、eval
949 0
Python json中一直搞不清的load、loads、dump、dumps、eval
|
2月前
|
数据采集 监控 数据可视化
你的数据质量可靠吗?一份评估数据质量的实用指南
数据质量是企业数据驱动的生命线。本文深入探讨其六大核心维度:准确性、完整性、一致性、及时性、唯一性与有效性,解析低质数据带来的决策失误、效率低下等痛点,并分享如何通过业务与技术协同,借助工具实现质量规则的自动化监控与持续改进,构建可信数据体系。
|
8月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
348 0
|
物联网 数据格式 异构计算
3种大模型微调技术对比:全参、LoRA、RAG,你的项目该怎么选?
本文深入浅出地解析了大语言模型适应专业场景的三种核心技术:**全参数微调 (Full Fine-Tuning)**、**LoRA微调 (Low-Rank Adaptation)** 和 **检索增强生成 (RAG)**。 文章通过生动的比喻,将通用大模型比作“通才毕业生”,而三种技术则是为其“开小灶”的不同路径: - **全参数微调**:成本高昂的“回炉重造”,效果深入但资源消耗巨大。 - **LoRA微调**:高性价比的“技能插件”,以极低成本实现专业能力定制。 - **RAG**:即插即用的“外挂知识库”,无需训练模型,通过检索外部知识实时生成答案。
|
3月前
|
机器学习/深度学习 安全 算法
PPO最强,DPO一般?一文带你了解常见三种强化学习方法,文末推荐大模型微调神器!
大模型如何更懂人类?关键在于“对齐”。PPO、DPO、KTO是三大主流对齐方法:PPO效果强但复杂,DPO平衡高效,KTO低成本易上手。不同团队可根据资源选择路径。LLaMA-Factory Online让微调像浏览器操作一样简单,助力人人皆可训练专属模型。
790 3
PPO最强,DPO一般?一文带你了解常见三种强化学习方法,文末推荐大模型微调神器!
|
10月前
|
人工智能 搜索推荐 定位技术
让兵马俑“活”过来——增强现实正在悄悄改变我们的旅游体验
让兵马俑“活”过来——增强现实正在悄悄改变我们的旅游体验
348 11
|
存储
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解(一)
【高阶数据结构】二叉树进阶探秘:AVL树的平衡机制与实现详解
231 1
|
存储 机器学习/深度学习
【数据结构】二叉树全攻略,从实现到应用详解
本文介绍了树形结构及其重要类型——二叉树。树由若干节点组成,具有层次关系。二叉树每个节点最多有两个子树,分为左子树和右子树。文中详细描述了二叉树的不同类型,如完全二叉树、满二叉树、平衡二叉树及搜索二叉树,并阐述了二叉树的基本性质与存储方式。此外,还介绍了二叉树的实现方法,包括节点定义、遍历方式(前序、中序、后序、层序遍历),并提供了多个示例代码,帮助理解二叉树的基本操作。
1304 13
【数据结构】二叉树全攻略,从实现到应用详解
2022年最新最详细的IntelliJ idea高效插件的介绍安装,让你的工作效率提升10倍
这篇文章详细介绍了10款IntelliJ IDEA的高效插件,包括Codota代码智能提示、Key Promoter X快捷键提示、CodeGlance代码缩略图、Lombok代码简化、阿里巴巴代码规范检查、SonarLint代码质量检查、Save Actions格式化代码、Translation翻译、Rainbow Brackets彩虹括号和Nyan Progress Bar彩虹进度条插件,旨在帮助提升开发效率和代码质量。
2022年最新最详细的IntelliJ idea高效插件的介绍安装,让你的工作效率提升10倍

热门文章

最新文章