二叉树前序、中序、后序遍历(递归、非递归)

二叉树的前序、中序、后序遍历(递归、非递归写法) 文章目录一、什么是二叉树?二、二叉树的基本概念三、二叉树的三种遍历方式1.前序遍历(preordertraversal)1.中序遍历(inordertraversal)1.后序遍历(postordertraversal)四、代码实现1.建树过程2.递归写法3.非递归写法4.完整代码 一、什么是二叉树? 二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。 阅读详情

前序遍历:(练习题)

迭代法一:

int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}


int* preorderTraversal(struct TreeNode* root, int* returnSize){
    if(root==NULL){
        *returnSize = 0;
        return (int*)malloc(sizeof(int)*0);
    }
    int size = TreeSize(root);//获得树的节点数
    int* ans = (int*)malloc(sizeof(int)*size);//开辟数组
    struct TreeNode** s = (struct TreeNode*)malloc(sizeof(struct TreeNode*)*size*2);//模拟栈
    int top = 0;
    int i = 0;
    struct TreeNode* node = root;
    while(i<size){
        if(node){
            ans[i++] = node->val;
            s[top++] = node;
            node = node->left;
        }else{
           node = s[--top];
           node = node->right; 
        }
    }
    free(s);//释放内存
    *returnSize = size;
    return ans;
}

迭代法二:


int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    if(root==NULL){
        *returnSize = 0;
        return (int*)malloc(sizeof(int)*0);
    }
    int size = TreeSize(root);//获得树的节点数
    int* ans = (int*)malloc(sizeof(int)*size);//开辟数组
    struct TreeNode** s = (struct TreeNode*)malloc(sizeof(struct TreeNode*)*size*2);//模拟栈
    int top = 0;
    int i = 0;
    s[top++] = root;
    while(i<size){
        struct TreeNode* node = s[--top];//出栈
        if(node){
            if(node->right) s[top++] = node->right;
            if(node->left) s[top++] = node->left;
            s[top++] = node;
            s[top++] = NULL;//表明前一个根节点已经访问过子树
        }else{
            ans[i++] = s[--top]->val;
        }

    }
    free(s);//释放内存
    *returnSize = size;
    return ans;
}

迭代法三:

int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int size = TreeSize(root);//获得树的节点数
    int* ans = (int*)malloc(sizeof(int)*size);//开辟数组
    struct TreeNode** s = (struct TreeNode*)malloc(sizeof(struct TreeNode*)*size);//模拟栈
    int top = 0;
    int i = 0;
    s[top++] = root;
    while(i<size){
        struct TreeNode* node = s[--top];//出栈
        ans[i++] = node->val;
        //左右子树入栈
        //根左右(栈先进后出,先入右子树后入左子树)
        if(node->right)  s[top++] = node->right;
        if(node->left)  s[top++] = node->left;

    }
    free(s);//释放内存
    *returnSize = size;
    return ans;
}

递归法:

void preorder(struct TreeNode* root,int* ans,int* i){
    if(root==NULL) return ;
    ans[(*i)++] = root->val;
    preorder(root->left,ans,i);
    preorder(root->right,ans,i);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize){
    int* ans = (int*)malloc(sizeof(int)*101);
    int i= 0;
    preorder(root,ans,&i);
    *returnSize = i;
    return ans;
}

中序遍历:(练习题)

迭代法一:


int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}

int* inorderTraversal(struct TreeNode* root, int* returnSize){
    if(root==NULL){
        *returnSize=0;
        return (int*)malloc(sizeof(int)*0);
    }
    int size = TreeSize(root);
    *returnSize = size;
    int* ans = (int*)malloc(sizeof(int)*size);
    struct TreeNode** s = (struct TreeNode*)malloc(sizeof(struct TreeNode*)*size*2);//模拟栈
    int i = 0;
    int top = 0;//栈顶
    s[top++] = root;
    while(i<size){
        struct TreeNode* node = s[--top];
        if(node){
            if(node->right) s[top++] = node->right;
            s[top++] = node;
            s[top++] = NULL;
            if(node->left) s[top++] = node->left;
        }else{
            ans[i++] = s[--top]->val;
        }
    }
    free(s);
    return ans;
}

迭代法二:

//节点个数
int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}

int* inorderTraversal(struct TreeNode* root, int* returnSize){
    if(!root){//空树
        *returnSize = 0;
        return (int*)malloc(sizeof(int*)*0);
    }
    int size = TreeSize(root);
    *returnSize = size;
    int* ans = (int*) malloc(sizeof(int)*size);
    struct TreeNode** s = (struct TreeNode*)malloc(sizeof(struct TreeNode*)*size*2);//模拟栈
    int i = 0;
    int top = 0;//栈顶
    struct TreeNode* node = root;
    while(i<size){
        if(node){//一直检索左孩子
            s[top++] = node;//入栈
            node = node->left;//一路向左
        }else{//出栈
            node = s[--top];//栈顶元素出栈
            ans[i++] = node->val;
            node = node->right;//右子树
        }
    }
    free(s);
    return ans;
}

递归法:

int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}

void inorder(struct TreeNode* root,int* ans,int* i){
    if(root==NULL) return;
    inorder(root->left,ans,i);
    ans[(*i)++] = root->val;
    inorder(root->right,ans,i);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize){
    int size = TreeSize(root);
    int* ans = (int*)malloc(sizeof(int)*size);
    int i = 0;
    inorder(root,ans,&i);
    *returnSize = size;
    return ans;
}

后序遍历:(练习题)

迭代法一:

int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}


int* postorderTraversal(struct TreeNode* root, int* returnSize){
    if(root==NULL) {
        *returnSize = 0;
        return (int*)malloc(sizeof(int)*0);  
    }
    int size = TreeSize(root);//获得树的节点数
    int* ans = (int*)malloc(sizeof(int)*size);//开辟数组
    struct TreeNode** s = (struct TreeNode*)malloc(sizeof(struct TreeNode*)*size*2);//模拟栈
    int top = 0;
    int i = 0;
    s[top++] = root;
    //先根右左进栈,之后左右根出栈
    //这里注意如果root本来就为空,下面则会发生越界 所以不建议while(top>0) 或者开头便判断是否为空
    while(i<size){
        struct TreeNode* node = s[--top];//弹出栈顶元素 并且pop掉
        if(node){//元素不为NULL
            s[top++] = node;
            s[top++] = NULL;//NULL标记前面根节点已经被访问
            if(node->right) s[top++] = node->right;
            if(node->left) s[top++] = node->left;
        }else{
            ans[i++] = s[--top]->val;
        }
        
    }
    free(s);//释放内存
    *returnSize = size;
    return ans;
}

迭代法二:


int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}


int* postorderTraversal(struct TreeNode* root, int* returnSize){
    if(root==NULL) {
        *returnSize = 0;
        return (int*)malloc(sizeof(int)*0);  
    }
    int size = TreeSize(root);//获得树的节点数
    int* ans = (int*)malloc(sizeof(int)*size);//开辟数组
    struct TreeNode** s = (struct TreeNode*)malloc(sizeof(struct TreeNode*)*size*2);//模拟栈
    int top = 0;
    int i = 0;
    struct TreeNode* node = root;
    struct TreeNode* r = NULL;
    while(i<size){
        if(node){
            s[top++] = node;
            node = node->left;
        }
        else{
            node = s[top-1];
            if(node->right&&r!=node->right){//防止重复遍历右子树
                node = node->right;
            }
            else{
                r = s[--top];
                ans[i++] = r->val;
                node = NULL;
            }
        }
    }
    free(s);//释放内存
    *returnSize = size;
    return ans;
}

递归法:

int TreeSize(struct TreeNode* root){
    return root==NULL?0:TreeSize(root->left)+TreeSize(root->right)+1;
}

void postorder(struct TreeNode* root,int* ans,int* i){
    if(root==NULL) return ;
    postorder(root->left,ans,i);
    postorder(root->right,ans,i);
    ans[(*i)++] = root->val;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize){
    *returnSize = TreeSize(root);
    int* ans = (int*)malloc(sizeof(int)*(*returnSize));
    int i = 0;
    postorder(root,ans,&i);
    return ans;
}

二叉树前序、中序、后序遍历非递归写法的透彻解析 前言 在前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历。递归写法,只要理解思想,几行代码。可是非递归写法却很不容易。这里特地总结下,透彻解析它们的非递归写法。其中,中序遍历的非递归写法最简单,后序遍历最难。我们的讨论基础是这样的: 阅读详情

相关推荐

C/C++ 二叉树的非递归遍历(前序、中序、后序非递归遍历)

二叉树的非递归遍历C/C++实现: 非递归先序遍历代码: void PreOrderTraversal (struct tree* root) { //非递归先序遍历 struct tree* temp = root; while (temp != NULL || S.top > 0) { while (temp != NULL) { ...

SanpTap的博客 2596

手撕二叉树遍历(前序 + 中序 + 后序 递归 + 非递归 代码实现 + 例题)

文章目录前引二叉树遍历介绍1、二叉树前序遍历1、二叉树前序遍历代码(递归)2、二叉树前序遍历代码(非递归)2、二叉树中序遍历1、二叉树中序遍历代码(递归)2、二叉树中序遍历代码(非递归)3、二叉树后序遍历1、二叉树后序遍历代码(递归)2、二叉树后序遍历代码(非递归)二叉树遍历例题 前引 刚刚才写完了手撕最小堆的博客 就想了 是不是也得写一下二叉树遍历呢 哈哈 因为前段时间才写过 而且那个时候理解花了很多时间 所以现在手撕了三个遍历 大概花了5分钟左右 力扣三道题 前中后序遍历也就一次性全部AC啦 把这

Love 6's Private Blog 1万+

C++实现递归,非递归遍历二叉树(前序,中序,后序)

初学二叉树那会儿,始终掌握不好二叉树的遍历方法,更认为非递归遍历晦涩难懂没有掌握的意义。实际上非递归的遍历方法很有用处,由于每次递归都需要将函数的信息入栈,当递归层数太深很容易就导致栈溢出,所以这个时候就必须用到非递归遍历二叉树了。而且,当看懂非递归遍历后,你会发现,其实非递归也很简单。 我们知道,要想处理二叉树,离不开其遍历方式。遍历二叉树有三种方式,前序遍历,中序遍历,后序遍历,每种...

Hairy_Monsters的博客 4165

非递归实现二叉树的前序,中序,后序遍历打印

前言:前面这篇文章主要是用递归的思想写了一颗二叉树,其中包括前序建树;前序,中序,后序遍历打印,层序遍历(非递归);求高度;求节点数;求叶子节点数;求第k层结点树等;详情请看: 递归实现二叉树的前,中,后序打印在我们了解了最简单的递归遍历以后,现在来说说用栈辅助,非递归实现二叉树的前序,中序,后序遍历打印 一:非递归实现前序遍历打印 1. 前序遍历,访问的顺序为根->左->右; 2. 前

4927

一文彻底搞定二叉树的前序、中序、后序遍历(图解递归非递归)

前言 大家好,我是bigsai,在数据结构与算法中,二叉树无论是考研、笔试都是非常高频的考点内容,在二叉树中,二叉树的遍历又是非常重要的知识点,今天给大家讲讲二叉树的层序遍历。 这部分很多人可能会但是需要注重一下细节。 前面介绍了二叉排序树的构造和基本方法的实现,遍历也是比较重要的一环,并且二叉树的层序遍历也是bfs的最简单情况,这里我就将二叉树的层序遍历以及常考问题给大家分享一下。 在了解二叉树的遍历之前,需要具备数据结构与算法有队列、递归、栈、二叉树,这些内容咱们前面都有讲过,有这方面知识欠缺的同学可以

bigsai 1万+

ScottPlot vs LiveCharts:WPF图表库性能对比与MVVM适配方案

本文深度对比了WPF图表库ScottPlot与LiveCharts在性能与MVVM架构适配上的表现。通过十万级数据点的基准测试,ScottPlot在渲染速度与内存占用上优势显著。文章重点探讨了两种库在MVVM模式下的集成方案,为开发者根据项目需求(如实时监控或快速原型)进行技术选型提供了实战指导。

lll78的博客 245

二叉树系列(2)前序中序后序遍历的递归和非递归实现

递归地对二叉树进行遍历的做法比较好理解。有一颗树,长成这个样子。 下面分别是对它进行三序遍历的结果: 前序递归 //前序递归 void pre_order(link t, void (*visit)(link)) { if(!t) return; visit(t); pre_order(t->l, visit); pre_order(t->r, visit); }

BUILD 2271

ANSYS Workbench接触分析实战:从算法选择到收敛难题破解

本文深入解析ANSYS Workbench接触分析的核心技术与实战技巧,涵盖四大接触算法选择、收敛难题破解秘籍及典型场景参数设置。通过实际案例演示如何优化接触刚度、pinball区域和非对称行为等关键参数,帮助工程师有效解决结构非线性问题,提升仿真效率和精度。

weixin_28705087的博客 358

非递归实现二叉树的前序、中序、后序遍历

根据二叉树的前序和中序遍历结果还原二叉树、根据二叉树的中序和后序遍历结果还原二叉树

m0_55752775的博客 1876

从共现矩阵到共现图一步到位——详解版

1.共现矩阵 判断大量不同文本之间,相邻词的联系,两词在所有文本中相邻的次数在矩阵中用数值表示。(参考此) 例子如下: 1.1 文本 • I like deep learning. • I like NLP. • I enjoy flying. 1.2 共现矩阵 2.共现图 2.1 数据预处理(节点和边) 获取文件node.csv和edge.csv。代码详见github仓库 2.2 共现图的制作 2.2.1 gephi的安装(参考此) (1)先下载gephi (2) 再配置java环境(下载java1.8

微乐的博客 4401

同态加密与SEAL库实战:CKKS参数调优避坑指南

本文深入探讨了同态加密技术中CKKS方案的参数调优实践,重点解析了SEAL库中`poly_modulus_degree`、`coeff_modulus`和`scale`三大核心参数的配置技巧与避坑指南。通过实战案例展示了如何平衡计算深度、精度与性能,为开发者提供了一套完整的参数优化方法论,帮助避免常见的'scale out of bounds'等错误,显著提升同态加密应用的可靠性和效率。

weixin_29315569的博客 228

【二叉树Java】二叉树遍历前序中序后序遍历的非递归写法

二叉树遍历的非递归写法

liuwanqing233333的博客 3133

Linux iperf 进行跑流测试时,为啥单条流会有速率上不去的问题?

iperf

1042484520@qq.com(邮箱) 3086

手写非递归遍历二叉树、前序、中序、后序

前序、中序、后序遍历二叉树

身在边城 心在编程 395

Oracle EBS 寄销/VMI(2)-->采购篇

上篇有一部分设置需要建BPA后,将BPA编号与批准的供应商相关联.     本篇主要是讲的内容:一揽子采购协议-->准标采购订单-->收接入库-->子库转移-->创建冲减通知-->'按接收开票' 自动开票程序 1. PO-->采购订单à采购订单 创建一揽子采购协议,确定物料

陈显平的专栏-Oracle EBS 1万+

把 LangGraph 当“工作流引擎”用:与传统 BPM 的差异与融合策略

首先,我们来回顾一下有限状态机(FSM)的基本定义——一个 FSM 可以用一个五元组MQΣδq0FMQΣδq0​FQQQ有限状态集合,包含 FSM 所有可能的状态;Σ\SigmaΣ有限输入字母表,包含 FSM 所有可能的输入;δ\deltaδ状态转移函数,定义了 FSM 从当前状态q∈Qq \in Qq∈Q接收输入σ∈Σσ∈Σ后,转移到的下一个状态q′∈Qq' \in Qq′∈Q,即δQ×Σ→QδQ×Σ→Q。

AI 原生应用开发的博客 227

二叉树前序中序后序遍历的非递归写法(Java)

二叉树前序中序后序遍历的递归遍历非常简单,这里就写一下非递归的方法。 核心思路是把每一个结点看成父节点,叶子结点是左右孩子是null的父结点。 前序遍历 思路: 使用一个栈来存储结点,以便回到之前的父结点。 不断往左子树深入并不断先打印值再入栈直到左叶子的空左孩子 弹出栈顶,将指针指向它的右孩子 循环1,2步骤直至栈为空且指针也为空(意思是当栈为空但指针不为空时,继续。比如当栈顶元素...

ChaunceyChen的博客 3287

2026年全国青少年信息素养大赛复赛真题(算法应用主题赛C++小学组:带解析)(7月4日试卷一)【文末附答案和解析】

2026年全国青少年信息素养大赛复赛真题(算法应用主题赛C++小学组:带解析)(7月4日试卷一)【文末附答案和解析】

王老师青少年编程 1738

二叉树三种(前序中序后序)遍历方式(递归版和非递归版)

递归遍历二叉树比较容易理解,就直接按照遍历方式的定义来做就行了。关键是非递归遍历二叉树。 先说一下递归遍历二叉树,三种序列遍历方式的大致结构是一样的,都是先递归遍历左子树,再递归遍历右子树,区别就在于访问节点的顺序不同,先序遍历是先访问根节点再访问左子树和右子树,所以是在一开始就输出节点值,而中序遍历是先访问左子树再访问根节点最后访问右子树,也就是说在递归遍历完当前节点左子树后进行当前节点值输出,而后序遍历是访问完当前节点左子树和右子树后再进行当前节点值的输出。 而非递归遍历二叉树的实现过程的大体框架也

AC__dream的博客 3404

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

二叉树的遍历;前序 中序 后序遍历二叉树;递归 非递归实现; 重建二叉树;编程之美重建二叉树

最近复习数据结构,重点看了下二叉树,这篇文章主要介绍下二叉树的遍历,包括中序遍历、前序遍历和后序遍历;同时利用二叉树的中序遍历和前序遍历或者后序遍历来重建一棵二叉树。 下面先给出对于某个节点的前序、中序、后序遍历的定义: 1、前序遍历: 先访问该节点,然后在递归遍历其左子树,然后再访问其右子树 2、中序遍历: 先递归遍历其左子树,然后访问该节点,然后再递归遍历其右子树 3、后序遍历: 先递归遍历其左子树,然后递归遍历其右子树,然后在访问该节点。   下面先说明如何实现二叉树的三种遍历,然后

疯狂算法~ 2万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

非递归前序中序后序遍历二叉树

二叉树的遍历问题是二叉树的基本问题,也是在数据结构中比较常见的问题,二叉树的遍历分为前序遍历、中序遍历和后序遍历,其中这些某序指的是每棵子树根节点的位置,对于左右分支来说,顺序永远都是先左后右。我相信学过数据结构的姑娘和小伙子一定对这个都有所了解,并且也都能写出对已知二叉树进行遍历的代码。

abpenguin的博客 2149

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

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

二叉树的遍历方法是以打印根节点的顺序来命名的。先打印根节点就叫做前序遍历,先打印左结点后打印根节点就叫做中序遍历,最后打印根节点就叫做后序遍历。以下面一颗二叉树为例,本文分析这颗二叉树前序、中序、后序非递归遍历的方法。虽然这三种遍历的策略不一样,但是遍历二叉树本质上就是递归,而递归在计算机内部就是不停的压栈,保留现场。所以我们能够很容易的想到用栈这种结构实现非递归遍历。 上图给出了非递归前序遍历的过程。 前序遍历 前序遍历就是对每个节点按照"根左右"的顺序进行遍历。本质上是一种递归,由于每个节点的遍历策略

Thatcher Li 523

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

ps:看完这篇文章你将掌握二叉树的非递归前序遍历、中序遍历和后续遍历,以及它们在leetcode上一些题如#94,#538,#938等题的应用 一、前序遍历 首先说前序遍历,要了解前序遍历的非递归写法,首先要弄明白前序遍历的遍历策略。考虑一种最简单的二叉树模型,模型中包括了根节点,左子树和右子树,在前序遍历中,对于这样一颗二叉树,前序遍历的意思就是一定是以Root节点、左子树、右子树的顺序一次遍历各个节点,当遍历左子树时左子树又可以看作另一颗二叉树,因此这是一种典型递归的思想。 注意到上述遍历过程中,遍历

qq_38001359的博客 861

实现二叉树的前序/中序/后序递归、非递归遍历

实现二叉树的前序/中序/后序非递归、递归遍历

景初浅行 1288

非递归前序、中序、后序遍历二叉树

辅助栈实现非递归前序、中序、后序遍历二叉树

sherlockreal的博客 634
上一篇: LeetCode 822. 翻转卡片游戏
下一篇: 探讨计算机内存管理:分页与分段的地址空间维度差异(为什么分页机制中逻辑地址空间是一维的,而分段机制中逻辑地址空间是二维的?)
天皓Oo
博客等级 码龄5年 337粉丝 61原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值