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

二叉树的前序、中序、后序遍历(递归、非递归写法) 文章目录一、什么是二叉树?二、二叉树的基本概念三、二叉树的三种遍历方式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万+

告别龟速与断连:Arduino IDE下ESP32及ESP32-CAM一站式环境部署指南

本文提供Arduino IDE下ESP32及ESP32-CAM一站式环境部署指南,解决下载速度慢、断连等常见问题。通过国内镜像源加速、详细步骤讲解和ESP32-CAM专属配置技巧,帮助开发者快速完成环境搭建,避免常见陷阱,提升开发效率。

weixin_30576827的博客 771

二叉树系列(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

RK3588+TRL8367s 四网口千兆交换机配置与优化实战

本文详细介绍了基于RK3588高性能SoC与TRL8367s千兆交换芯片构建四网口交换机的完整实战流程。内容涵盖硬件连接、设备树配置、内核驱动加载、性能优化及常见问题排查,重点解析了RGMII时序调试、DSA架构配置等关键步骤,为嵌入式网络设备开发提供实用指南。

weixin_29266647的博客 673

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

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

m0_55752775的博客 1876

先进封装Interposer仿真步骤及说明

摘要: Interposer仿真是2.5D/3DIC封装设计的关键环节,涵盖信号完整性(SI)、电源完整性(PI)、热及结构应力分析。流程分为五个阶段:1)前处理,定义层叠结构与材料属性;2)参数提取,通过3D电磁建模获取TSV、传输线等寄生参数;3)仿真设置,选择求解器并设定频率范围;4)结果分析,评估信号损耗、阻抗及电源网络性能;5)后处理,进行多物理场协同仿真并生成模型。核心挑战在于多尺度与多物理场耦合,需优先确保高速信号与电源网络的仿真精度。常用工具包括Ansys HFSS、Cadence Sigr

DSY_0324的博客 1345

ESP32-S3 SPI接口实战:从引脚分配到高速通信配置

本文详细解析了ESP32-S3的SPI接口配置与高速通信优化技巧,从引脚分配到软件配置,再到DMA传输和时钟优化,帮助开发者快速掌握SPI通信技术。特别针对ESP32-S3的SPI2接口进行了实战演示,包括硬件连接和常见问题排查,适用于各类嵌入式开发项目。

weixin_29189373的博客 677

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

二叉树遍历的非递归写法

liuwanqing233333的博客 3133

手把手教你用FPGA实现SGMII接口:从IP核配置到板级调试全流程

本文详细介绍了如何在Xilinx 7系列FPGA上实现SGMII(Serial Gigabit Media Independent Interface)接口的全流程,包括IP核配置、约束编写和硬件调试。通过具体的硬件选型建议、软件工具链配置和PCB设计规范,帮助开发者快速构建稳定可靠的千兆通信链路,并提供了常见故障排查和性能优化技巧。

weixin_29194693的博客 296

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

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

身在边城 心在编程 395

使用MeshLab高效对齐3D模型:从OBJ导入到坐标修正全流程

本文详细介绍了使用MeshLab高效对齐3D模型的全流程,涵盖从OBJ导入、坐标修正到最终导出的核心步骤。通过将模型中心归位至坐标原点,并利用主轴对齐功能快速摆正模型,为后续的3D打印、体素化等处理奠定精确的几何基础。

weixin_29313423的博客 92

【S32K3 MCAL配置】-4.1-CAN Driver:如何解决CAN帧发送丢帧问题

【S32K3 MCAL配置】-4.1-CAN Driver:如何解决CAN帧发送丢帧问题

「汽车电子助手」的博客 1442

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

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

ChaunceyChen的博客 3287

YOLO模型从10MB瘦到2MB!剪枝+INT8量化双方案(精度损失<1%,附部署代码)

摘要:本文介绍了一种针对边缘设备的YOLO模型轻量化方案,通过"结构化剪枝+INT8量化"组合技术,将YOLOv8n模型从6.4MB压缩至2MB,体积减少68.75%,推理速度提升80%,同时保持精度损失小于1%。文章详细讲解了剪枝工具选择、通道剪枝实现、量化校准等关键步骤,并提供了完整的代码示例。特别强调了剪枝保留率、校准集使用、微调必要性等实践要点,帮助开发者在树莓派等资源受限设备上实现高效目标检测。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 756

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

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

AC__dream的博客 3404

VC中sqlite的使用

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

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

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

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

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

疯狂算法~ 2万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

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

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

abpenguin的博客 2149

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

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

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

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、付费专栏及课程。

余额充值