二叉树后续遍历算法

二叉树的前序、中序、后序、层序遍历,递归和迭代两大类解题思路,每类细分不同解法【完整版】附PDF文档 一、二叉树的前序遍历 二叉树的前序遍历的记忆法则是“根左右",即先遍历根节点,再遍历左子树节点,再遍历右子树节点。 以上图为例,前序遍历的结果是【A, B, D, E, C, F, G】 1.1 解题思路:递归 递归是我们实现前中后序遍历最常用的方法。 什么问题可以采用递归求解呢? 需要满足三个条件: 一个问题的解可以分解为若干个子问题的解; 这个问题与分解的子问题,除了数据规模不同外,求解思路相同 存在递归终止条件。 那么在知道一个问题可以采用递归实现之后,如何写出递归代码呢? 关键在于能写出递归 阅读详情

二叉树的后序遍历顺序为,root->left, root->right, root,因此需要保存根节点的状态。显然使用栈来模拟递归的过程,但是难点是怎么从root->right转换到root。

 

方法一

对于节点p可以分情况讨论

1. p如果是叶子节点,直接输出

2. p如果有孩子,且孩子没有被访问过,则按照右孩子,左孩子的顺序依次入栈

3. p如果有孩子,而且孩子都已经访问过,则访问p节点

 

如何来表示出p的孩是否都已经访问过了呢?

最暴力的方法就是对每个节点的状态进行保存,这么做显然是可以的,但是空间复杂度太大了。

我们可以保存最后一个访问的节点last,如果满足 (p->right==NULL && last ==p->left) || last=p->right,那么显然p的孩子都访问过了,接下来可以访问p

代码简单思路清晰!


 
#include <stdlib.h>
#include <iostream>
#include  <vector>
#include  <stack>
using namespace std;
// 定义结点类型
 struct node
{
    int data;
    struct node* left;
    struct node* right;
    node (int x):data(x),left(NULL),right(NULL){}
    
} ;

vector<int> Postorder(node* root)
{   
    vector <int> res;
    if(root ==NULL)
    return res;
    node* p = root;
    int flag = 1;
    node * t = NULL;
    stack<node *> sta;
    sta.push(p);
    cout << 1 << endl;
    while( !sta.empty())
    {
            p = sta.top();
            while(p->left != NULL)                    // 循环,将所有最左结点压栈
            {
                p = p -> left;
                sta.push(p);
            }
            flag = 1;                           // 辅助变量flag为1表示当前结点的左孩子为空或者已被访问
            t = NULL;                           // 指针变量t指向当前结点的前驱结点
            while( !sta.empty() && flag == 1)
            {
                p = sta.top();                  // 注意:这里只是获取栈顶元素,而并没有出栈
                if(p->right == t)              // 如果当前结点右孩子为空,或者已经被访问过,则访问当前结点
                {
                    cout << p->data;
                    res.push_back( p->data);
                    sta.pop();        // 当前结点出栈
                    t = p;                      // 指针变量指向当前结点
                }
                else                            // 如果当前结点右孩子不为空,则先去处理右孩子
                {
                    p = p->right;              // 处理右孩子
                    flag = 0;                   // *t的左孩子未被访问,flag置为0
                }
            }
        }
 return res;
 
}

int main()
{
        node a(1);
        node b(2);
        node c(5);
         node d(3);
         node e(4);
          node f(6);
          a.left = &b;
          a.right =  &c;
          b.left = &d;
          b.right = &e;
          c.right = &f; 
          vector<int> res = Postorder( &a );
          return 0;
}

方法二:

和二叉树先序遍历、中序遍历非递归算法一样,后序遍历非递归算法同样是使用栈来实现:从根结点开始,将所有最左结点全部压栈,每当一个结点出栈时,

都先扫描该结点的右子树,只有当一个结点的左孩子和右孩子结点均被访问过了,才能访问结点自身。

  二叉树后序遍历非递归算法实现如下:

#include <stdlib.h>
#include <stdio.h>
#define MAXSIZE 100
// 定义结点类型
typedef struct node
{
    int data;
    struct node* lchild;
    struct node* rchild;
} BTnode;

void Postorder(BTnode* t)
{
    BTnode* Seqstack[MAXSIZE];
    int top = -1;
    int falg = 1;
    BTnode* p;
    if(t != NULL)
    {
        do
        {
            while(t != NULL)                    // 循环,将所有最左结点压栈
            {
                top ++;
                Seqstack[top] = t;
                t = t->lchild;
            }
            flag = 1;                           // 辅助变量flag为1表示当前结点的左孩子为空或者已被访问
            p = NULL;                           // 指针变量p指向当前结点的前驱结点
            while(top > -1&& falg == 1)
            {
                t = Seqstack[top];              // 注意:这里只是获取栈顶元素,而并没有出栈
                if(t->rchild == p)              // 如果当前结点右孩子为空,或者已经被访问过,则访问当前结点
                {
                    top --;                     // 当前结点出栈
                    printf("%d ", p->data);
                    p = t;                      // 指针变量指向当前结点
                }
                else                            // 如果当前结点右孩子不为空,则先去处理右孩子
                {
                    t = t->rchild;              // 处理右孩子
                    flag = 0;                   // *t的左孩子未被访问,flag置为0
                }
            }
        }while(top > -1)
    }
    
}

上面代码实现了二叉树后序遍历非递归算法(重点看懂注释),接下来就说一说前面提到的该算法的一个特性了:就是当访问某个结点时,栈中所保存的元素

正好是这个结点的所有祖先。那么知道了这个特性,我们就很容易解决下面如下问题:

(1).当给定一个叶子结点,要求输出该叶子结点的所有祖先

(2).输出根结点到所有叶子结点的路径

(3).如果二叉树结点的值是数值,那么求每条路径上值之和,也可以利用二叉树后序遍历的非递归算法这个特性

#include <stdlib.h>
#include <stdio.h>
#define MAXSIZE 100
// 定义结点类型
 struct node
{
    int data;
    struct node* lchild;
    struct node* rchild;
    node (int x):data(x),lchild(NULL),rchild(NULL){}
    
} ;

void Postorder(node* t)
{
    node* Seqstack[MAXSIZE];
    int top = -1;
    int flag = 1;
    node * p;
    if(t != NULL)
    {
        do
        {
            while(t != NULL)                    // 循环,将所有最左结点压栈
            {
                top ++;
                Seqstack[top] = t;
                t = t->lchild;
            }
            flag = 1;                           // 辅助变量flag为1表示当前结点的左孩子为空或者已被访问
            p = NULL;                           // 指针变量p指向当前结点的前驱结点
            while(top > -1&& flag == 1)
            {
                t = Seqstack[top];              // 注意:这里只是获取栈顶元素,而并没有出栈
                if(t->rchild == p)              // 如果当前结点右孩子为空,或者已经被访问过,则访问当前结点
                {
                    top --;                     // 当前结点出栈
                    printf("%d ", p->data);
                    p = t;                      // 指针变量指向当前结点
                }
                else                            // 如果当前结点右孩子不为空,则先去处理右孩子
                {
                    t = t->rchild;              // 处理右孩子
                    flag = 0;                   // *t的左孩子未被访问,flag置为0
                }
            }
        }while(top > -1)
   ; }
    
}
int main()
{
     node a(1);
      node b(2);
        node c(5);
        node d(3);
         node e(4);
          node f(6);
          a.lchild =&b;
          a.rchild= &c;
          b.lchild =&d;
          b.rchild = &e;
          c.rchild = &f;
          //preorder(&a,0);
          //preorder1(&a);
          //preorder2(&a);
          //LeverOrder(&a);
          Postorder(&a);
          return 0;
}

 

 

 

 

 

二叉树的后序遍历算法(递归和非递归) 以下图所示的二叉树为例:图 1 二叉树后序遍历这棵二叉树的过程是:从根节点 1 出发,进入该结点的左子树;进入结点 2 的左子树,遍历左子树中的结点:进入结点 4 的左子树,但该结点没有左孩子;进入结点 4 的右子树,但该结点没有右子树;访问结点 4;进入结点 2 的右子树,遍历右子树中的结点:进入结点 5 的左子树,但该结点没有左孩子;进入结点 5 的右子树,但该结点没有右孩子;访问结点 5;访问结点 2; 阅读详情

相关推荐

XPe开发初体验(一)XPe概述

XP Embedded是微软Windows Embedded产品线中非常重要的一环,不过比起大名鼎鼎的Windows Embedded CE,XPe显得过于低调了。在接下来的一段时间里,我希望能够用六篇的篇幅来描述一下XPe的整个开发过程。这个系列文章主要是针对有Windows编程经验,但是没有嵌入式开发经验的开发者,提供一些概念和开发过程的初步介绍。XP Embedded是一个基于Windo

aawolf = new Mobile.MVP 1万+

二叉树遍历之后序遍历(非递归、递归)入门详解

二叉树后序遍历不如先序遍历简单,是相对最复杂的一种遍历方法。访问结点的次序是:“左—>右—>根”,也就是首先访问左子树,之后访问右子树,最后访问树根。对于左、右子树而言,其访问的次序依然是“左—>右—>根”。也就是说,对于每一棵子树,都是最后访问树根。...

sunnyoldboy博客 3万+

深入分析RAG知识库多模态数据预处理

多模态企业数据预处理是构建高质量RAG知识库的关键环节。本文详解了处理流程:1)文档格式识别与路由;2)多模态内容提取(文本、图像、音视频);3)结构解析与语义重建;4)数据清洗与增强;5)智能分块(强调语义完整性);6)元数据注入。推荐使用开源工具如PaddleOCR、Whisper、BLIP-2等,或商业API处理复杂场景,最终生成带丰富元数据的结构化内容,为后续向量化检索奠定基础。

qq_35354529的博客 1379

二叉树遍历方法——前、中、后序遍历(图解)

二叉树的前、中、后序遍历的递归与非递归算法

在夜里行走的博客 17万+

从SIGGRAPH审稿人视角看:什么样的TOG论文更容易被接收?

本文从SIGGRAPH审稿人视角深入解析TOG论文的审稿标准与投稿策略,揭示如何提升论文接收概率。重点探讨创新性、技术深度、实验验证等核心评分维度,并提供写作技巧与审稿意见应对策略,帮助研究者优化ACM Transactions on Graphics投稿质量。

weixin_33721344的博客 108

Tube-based MPC完全指南:RCI集合构造与Matlab实现

模型预测控制(MPC)在实际工程中常因模型失配和外部扰动导致硬约束被突破,而鲁棒控制中的Tube-based MPC通过将单条预测轨迹扩展为“管道”集合,为不确定性提供了严格的安全边界。其核心在于利用鲁棒控制不变集(RCI)离线构造安全域,再结合在线标称MPC与反馈校正实现约束的硬保证。针对非线性系统,利普希茨条件为等效扰动的放大和RCI的构造提供了理论基础,使得算法既能保留非线性描述,又不牺牲在线计算效率。该方法适用于带扰动和参数漂移的机械系统、过程控制及嵌入式控制场景。本文以摩擦力非线性系统为例,从RC

weixin_32642109的博客 216

二叉树的后续遍历(迭代法)

迭代法实现二叉树的后续遍历 1、递归版本 public static void dfs(TreeNode root){ if(root==null){ return; } if(root.left!=null) dfs(root.left); if(root.right!=null) dfs(root.right); System.out.println(root.val); } 从递归版本可以看出我们第一步需要遍历完所有的左节点 这里

qq502130297的博客 2589

2026年数据中心运行与管理专业人才培养基地建设方案(高职、数据中心运行与管理新专业、人才培养、专业代码:510310)

摘要: 为响应国家“东数西算”战略和数字经济需求,我校拟联合行业领军企业建设数据中心运行与管理人才培养基地。项目基于国家政策引导和产业快速发展背景,针对行业10万人才缺口,对标教育部新设专业标准(510310),分三阶段实施五年规划:专业奠基(2026-2028)、内涵深化(2028-2029)、辐射引领(2030-2031)。建设内容涵盖校企协同岗位能力分析、模块化课程开发(如网络管理、自动化运维等)、实训基地搭建及“课证融通”培养模式,重点培养基础设施、网络服务、运维托管三类岗位技能人才,目标建成区域性

啊碧根果的博客 1687

关于二叉树后续遍历算法的一点思考

二叉树的三种遍历方式,最贱的那个

kanbujian 585

【stm32+K210项目】基于K210与STM32协同工作的智能垃圾分类系统设计与实现(完整工程资料源码)

本系统采用SG90舵机Maix Bit摄像头STM32C8T6主控板以及LX_TRIG_MP3_V6.0语音播报模块,构建了一套高效的智能垃圾分类系统,综合运用了图像识别、语音播报及精准控制技术。SG90舵机负责控制垃圾桶的开盖操作。该舵机通过接收PWM信号来实现转动,内部有一个基准电路产生周期为20ms的PWM信号,通过外部脉冲信号的控制(高电平时间在0.5ms至2.5ms之间),使得舵机的输出轴转动到指定位置。舵机内的位置反馈电位计。

嵌入式技术开发 5099

在时间轴上联动多张内表:ABAP 的 PROVIDE ... ENDPROVIDE 区间联动迭代实战

PROVIDE 是 ABAP 中处理有效期区间数据的强大工具,它能自动将多张内表按时间维度切片并联合处理。其核心功能包括:指定区间边界字段(BOUNDS),定义外部总区间(BETWEEN),并通过工作区和标志位(VALID)标识每张表在当前子区间是否生效。该语法特别适合 HR 信息类型等有效期数据,能避免手动处理区间重叠、排序和空档等问题。使用时需注意字段投影(FIELDS)限制、工作区只读原则,以及异常处理(如区间重叠或未排序)。典型应用场景包括员工调岗记录、价格有效期管理等需要时间轴联动的业务逻辑。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1671

从二叉树的前序和中序得到后续遍历算法

public class ConvertToPost {                 private char[] preArr;                 private char[] inArr;                 private char[] postArr;                 public ConvertToPost(char[] preA

a343315623的博客 420

【数据集】GPM IMERG Daily Precipitation Dataset

GPM IMERG Daily Precipitation Dataset

WW、forever的博客 1219

C语言非递归实现二叉树的三种遍历算法:前序、中序、后续

C语言非递归实现二叉树的三种遍历算法:前序、中序、后续目录遍历的基本概念-必读遍历示意图-必看先序遍历中序遍历后序遍历 目录 遍历的基本概念-必读 二叉树由三个元素组成,分别是根节点D,左子树L,右子树R。理论上存在六种遍历方法,分别是:DLR(先序)、LDR(中序)、LRD(后序)、DRL、RDL、RLD。实际中只有前三种遍历算法,特点是: L在R之前 根据D的前、中、后三种位置分为三种 遍历可以借助递归调用实现,方法简单便捷,本文不再介绍。 本文利用栈实现遍历,栈的特点:先进后出。利用栈主要是将树的

TomOfJerry的博客 1015

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

二叉树先中续后续遍历算法代码解析

转载自https://blog.youkuaiyun.com/zhangxiangdavaid/article/details/37115355 并加上自己理解 中序遍历的递归定义:先左子树,后根节点,再右子树。如何写非递归代码呢?一句话:让代码跟着思维走。我们的思维是什么?思维就是中序遍历的路径。假设,你面前有一棵二叉树,现要求你写出它的中序遍历序列。如果你对中序遍历理解透彻的话,你肯定先找到左子树的最下...

ptgood的博客 571

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

顺序存储的二叉树的前序遍历、中序遍历、后续遍历算法

输入 第一行:二叉树中的结点个数n 之后的n行中,每一行包含两个数据 : number: 代表结点在完全二叉树中的层序编号(根节点编号是1) value: char 型的数据,代表结点的值 输出 三行 第一行为前序遍历序列 第二行为中序遍历序列 第三行为后序遍历序列 样例输入 3 1 a 2 b 3 c 样例输出 abc bac bca 代码: #in...

wcxyky的博客 2242

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

二叉树的后续遍历算法实现

1 // 递归算法 2 template <class T> 3 void postOrder(void (*visit)(BinTreeNode<T>* t), BinTreeNode<T>* root) 4 { 5 if (root != NULL) { 6 postOrder(visit, root-&gt...

weixin_34257076的博客 138

二叉树先序遍历、中序遍历、后续遍历算法

先序遍历二叉树的操作定义为: 若二叉树为空,则空操作; 否则 (1)访问根结点; (2)先序遍历左子树; (3)先序遍历右子树; 中序遍历二叉树的操作定义为: 若二叉树为空,则空操作; 否则 (1)中序遍历左子树; (2)访问根结点; (3)中序遍历右子树; 后序遍历二叉树的操作定义为: 若二叉树为空,则空操作; 否则 (1

fulinux的博客 3980

二叉树遍历算法1:前序遍历、中序遍历与后续遍历

二叉树的前序、中序、后续遍历递归和非递归算法。

weixin_43354152的博客 668

遍历二叉树的模板方法

二叉树的遍历二叉树示意图遍历序列遍历方案二叉树节点先序遍历(深度优先)中序遍历后续遍历层次遍历(广度优先遍历) 二叉树 示意图 1234567 遍历序列 先序遍历序列:[4、2、1、3、6、5、7] 中序遍历序列:[1、2、3、4、5、6、7] 后续遍历序列:[1、3、2、5、7、6、4] 遍历方案 二叉树节点 class TreeNode { int val; TreeNode left...

nhj_csdn的博客 293

darknet迭代多少次_第11篇:C++数据结构 二叉树的迭代模式

二叉树转换线性表的时间复杂度前一篇已经讨论了BST的递归遍历模式,那么你们知道前一篇的递归接口设计上有一些不太优雅的地方吗?查看如下递归版本,不难发现。其实三种递归遍历模式的实现代码存在一些共同点:就是算法实现的内部内嵌了ArrayList调用。//后序遍历的公开版本 template<class T> ArrayList<T>* BSTree<T>::post...

weixin_30016593的博客 110

236. 二叉树的最近公共祖先

题目描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(首先我们确定遍历顺序 ,本题我们使用后续遍历,简单的想法,如果我们遇到了遍历到节点,我们就往上进行返回。如果左子树遍历的节点 == 7 ,那么将 7 进行返回。相同如果右子树遍历到的节点 ==4 ,那么将 4 进行返回。如果不存在 与目标值相等节点,那么向上返回 nullptr。

qq_62989250的博客 266

二叉树的遍历

先序遍历void preOrderTraverse(BiTree T){ InitStack(S); Push(S,T); BiNode * p; while(!StackEmpty(S)){ Pop(S,p); visit(p); if(p->rchild!=null) Push(S,p->rchild);

www.yiye.tech 325

剑指 Offer 32 - I. 从上到下打印二叉树

很明显这里不能用解决树问题最常用的前序,中序,后续算法。结合队列先进先出的特点,可以利用队列来完成此题。 我的代码: class Solution { public int[] levelOrder(TreeNode root) { if (root == null) return new int[0]; LinkedList<TreeNode> list = new LinkedList<>(); ArrayList..

qq_32816723的博客 109
上一篇: 深度优先搜素生成排列组合
下一篇: 待解决的小问题
runner668
博客等级 码龄11年 161粉丝 137原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值