news 2026/6/10 9:58:39

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

作者头像

张小明

前端开发工程师

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

后序遍历的递归算法核心思想是:按照“左子树 → 右子树 → 根节点”的顺序访问二叉树中的每个节点。以下是完整的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)。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/7 9:11:11

YOLOv8安防监控场景应用:异常行为初步识别

YOLOv8安防监控场景应用&#xff1a;异常行为初步识别 在城市地铁站的早高峰时段&#xff0c;摄像头画面中人群涌动。传统监控系统只能记录影像&#xff0c;而智能分析平台却能实时识别出某位乘客突然跌倒、长时间未起身&#xff0c;并自动触发告警——这一变化的背后&#xf…

作者头像 李华
网站建设 2026/5/30 8:59:49

Karate DSL:API测试自动化的简洁之道

在当今快速迭代的软件开发环境中&#xff0c;API测试自动化已成为确保产品质量的关键环节。然而&#xff0c;传统测试框架如Postman或RestAssured往往伴随着冗长的代码、复杂配置和陡峭学习曲线&#xff0c;让测试从业者陷入“脚本地狱”。面对这些挑战&#xff0c;Karate DSL&…

作者头像 李华
网站建设 2026/5/25 13:33:14

Locust:用Python构建高并发分布式负载测试体系

在当今微服务架构与云原生应用盛行的技术背景下&#xff0c;分布式负载测试已成为保障系统可靠性的核心手段。本文将深入解析如何利用纯Python工具链Locust&#xff0c;构建可横向扩展的现代化压力测试解决方案。 一、分布式负载测试的核心价值 系统瓶颈的真实模拟 在单体架构…

作者头像 李华
网站建设 2026/6/2 9:56:27

YOLOv8助力智慧交通:车辆行人检测解决方案

YOLOv8助力智慧交通&#xff1a;车辆行人检测解决方案 在城市交通日益复杂的今天&#xff0c;如何让系统“看懂”道路上的一举一动&#xff1f;传统监控摄像头虽然无处不在&#xff0c;但大多数仍停留在“录像回放”的阶段——发现问题靠人眼回溯&#xff0c;效率低、响应慢。…

作者头像 李华
网站建设 2026/6/7 22:10:11

从 98% 到3.8%,我的论文降 AI 率全过程

一、为什么手动降重总翻车&#xff1f;学术党必知的3大痛点“明明查重率达标了&#xff0c;导师却说论文有AI味要求重写&#xff01;”——这是不是你的真实写照&#xff1f;很多同学误以为同义词替换调整句式就能蒙混过关&#xff0c;结果陷入三大困局&#xff1a;❌ 痛点1&am…

作者头像 李华
网站建设 2026/5/28 7:49:24

降ai率超详细原理解析+工具推荐

一、为什么手动降重总翻车&#xff1f;学术党必知的3大痛点“明明查重率达标了&#xff0c;导师却说论文有AI味要求重写&#xff01;”——这是不是你的真实写照&#xff1f;很多同学误以为同义词替换调整句式就能蒙混过关&#xff0c;结果陷入三大困局&#xff1a;❌ 痛点1&am…

作者头像 李华