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

后序遍历的递归算法核心思想是:按照“左子树 → 右子树 → 根节点”的顺序访问二叉树中的每个节点

后序遍历的递归算法核心思想是:按照“左子树 → 右子树 → 根节点”的顺序访问二叉树中的每个节点。以下是完整的C语言实现示例:

#include<stdio.h>#include<stdlib.h>// 二叉树节点定义typedefstructTreeNode{intdata;structTreeNode*lchild;structTreeNode*rchild;}TreeNode;// 后序遍历递归实现voidPostOrder(TreeNode*root){if(root!=NULL){PostOrder(root->lchild);// 遍历左子树PostOrder(root->rchild);// 遍历右子树printf("%d ",root->data);// 访问根节点}}

关于三种遍历的路线逻辑,可以形象地理解为从根节点出发,沿二叉树外缘逆时针走一圈,每个节点会被经过三次:

  • 第一次经过时访问 → 先序遍历(根左右)
  • 第二次经过时访问 → 中序遍历(左根右)
  • 第三次经过时访问 → 后序遍历(左右根)

时间复杂度分析:
由于每个节点仅被访问一次,无论哪种遍历方式,总时间复杂度均为O(n)

空间复杂度分析:
主要消耗在系统调用栈上,取决于递归深度,即树的高度 h:

  • 平均情况(平衡树):O(log n)
  • 最坏情况(单枝树,退化为链表):O(n)

非递归遍历的基本思路是使用显式栈模拟函数调用栈的行为。以中序遍历为例,其非递归实现如下:

#include<stdbool.h>voidInOrderNonRecursive(TreeNode*root){TreeNode*stack[100];inttop=-1;TreeNode*p=root;while(p!=NULL||top!=-1){if(p!=NULL){stack[++top]=p;p=p->lchild;// 一直向左走}else{p=stack[top--];// 出栈printf("%d ",p->data);// 访问根p=p->rchild;// 转向右子树}}}

对于后序遍历的非递归实现,较为复杂,通常需要记录前驱节点或使用标志位来判断是否已遍历完左右子树。
实现二叉树的后序遍历非递归算法的关键在于:在不使用递归的情况下,正确判断何时访问根节点。由于后序遍历是“左→右→根”,我们必须确保在访问根节点前,其左右子树都已处理完毕。

常用方法是使用一个栈来保存待处理的节点,并借助一个指针记录上一次访问的节点(prev),从而判断当前节点是否可以被访问。

✅ 后序遍历非递归算法(单栈 + 标记法)

#include<stdio.h>#include<stdlib.h>typedefstructTreeNode{intdata;structTreeNode*lchild;structTreeNode*rchild;}TreeNode;voidPostOrderNonRecursive(TreeNode*root){if(root==NULL)return;TreeNode*stack[100];// 模拟栈inttop=-1;TreeNode*prev=NULL;// 记录上一次访问的节点TreeNode*curr=root;while(curr!=NULL||top!=-1){// 一直走到最左边if(curr!=NULL){stack[++top]=curr;curr=curr->lchild;}else{// 查看栈顶元素(不弹出)curr=stack[top];// 如果右子树为空或已被访问过,则可以访问当前节点if(curr->rchild==NULL||curr->rchild==prev){printf("%d ",curr->data);top--;// 弹出栈prev=curr;// 更新已访问节点curr=NULL;// 当前节点置空,避免重复入栈}else{// 否则转向右子树curr=curr->rchild;}}}}

🔍 算法逻辑说明:

  • 入栈顺序:从根开始一路向左,将路径上的所有节点入栈。
  • 判断访问时机
    • 若当前节点无右子树 → 可直接访问;
    • 或右子树已经被访问过(prev == curr->rchild)→ 表示左右子树均已处理,可访问根;
  • 否则:转向右子树继续处理。

🧪 示例:

对于如下二叉树:

1 / \ 2 3 / \ 4 5

后序遍历结果应为:4 5 2 3 1

该算法能正确输出此序列。


⏱️ 复杂度分析:

  • 时间复杂度:O(n),每个节点被压栈和弹栈一次。
  • 空间复杂度:O(h),h 为树的高度,最坏 O(n),平均 O(log n)。
http://www.jsqmd.com/news/172445/

相关文章:

  • 为了降 AI 率,我把能试的办法都试了一遍
  • 【AI开发避坑指南】LLM是大脑,RAG是记忆,MCP是手脚,Agent是员工?关系大揭秘!
  • YOLOv8单元测试编写规范与执行方法
  • YOLOv8单机多卡训练脚本启动方式
  • python中字符串,列表,元组,集合,字典常见的遍历方式整理
  • 北京大学:2025年AI时代的教育变革探索指南|附62页PDF文件下载
  • 中序遍历(基于栈的非递归实现)和层序遍历(基于队列的实现)是二叉树遍历中的两种重要方法
  • YOLOv8农业领域探索:病虫害识别与统计
  • 从 98% 到3.8%,我的论文降 AI 率全过程
  • 【地理加权回归GWR精讲】:基于R语言的空间非平稳性建模秘籍
  • YOLOv8历史记录追踪:git log高级用法
  • 线索二叉树是一种对普通二叉树进行扩展的数据结构,旨在提高遍历效率
  • 论文 AI 率到底怎么降?别再乱改了
  • Zabbix+Prometheus监控PHP服务,哪个更适合你的业务场景?
  • 天津大学:2025年人工智能赋能大学治理|附59页PDF文件下载
  • ‌核心结论:AI与无代码2025年移动测试的两大支柱
  • 论文到底怎么降ai率,一文说清楚所有的坑
  • 线索二叉树是对普通二叉树的优化结构,旨在提高遍历效率
  • AI认知地图:从AIGC到多模态模型,小白也能掌握的20个前沿概念
  • 【环境科学家都在用的AI工具】:基于R语言集成GPT的时空数据分析秘籍
  • AI辅助编程产生的问题增多研究显示缺陷率高1.7倍
  • 生成式AI在工具自动化中的应用
  • 耗时三分钟,我把论文ai率降到了3%
  • YOLOv8子模块管理:git submodule使用方法
  • YOLOv8标签版本发布:git tag创建与推送
  • YOLOv8模型版本管理:Git Tag发布规范说明
  • 为什么顶尖科研团队都在用R+GPT做生态建模?:深度解析其不可替代性
  • 为什么你的空间模型总是不显著?R语言LISA聚类分析告诉你真相
  • YOLOv8模型导出为ONNX格式,跨平台部署更高效
  • 互联网大厂Java面试实录:从Spring到微服务的全面探索