二叉树的先序、中序、后序遍历C++
一、二叉树的结构
二叉树的节点结构如下所示
template<typename T>
struct TreeNode
{T data; //数据TreeNode* left; //指向左孩子节点的指针TreeNode* right; //指向右孩子节点的指针TreeNode(T dat, TreeNode* lft = nullptr, TreeNode* rig = nullptr):data(dat), left(lft), right(rig) {}
};
如下所示是一个二叉树,其中的每一个节点都是由上述TreeNode节点的一个具体对象。
![](/assets/blank.gif)
二、先序遍历、中序遍历、后序遍历
1、什么是先序遍历
先遍历根(父)节点、再遍历左节点、最后遍历右节点。
注意:这里说的遍历并不是行走。毕竟我们能够先取到的指针只有根节点指针,而如果想找一个节点,则一定要先找到它的根节点。这里的遍历指的是“介绍”这棵树的方式。通常来讲,我们是使用的打印的方式“介绍”一棵树的。
所以,先序遍历展开来讲是:如果一棵树上有根节点,则先输出根节点,再输出左孩子节点、最后输出右孩子节点。
例如,上述图1中的二叉树,先序遍历输出是:3、9、20、15、7
2、什么是中序遍历
先遍历输出左孩子节点,再遍历输出根节点,最后遍历输出右孩子节点。
例如,上述图1中的二叉树,中序遍历输出是:9、3、15、20、7
3、什么是后序遍历
先遍历输出左孩子节点,再遍历输出右孩子节点,最后遍历输出根节点。
例如,上述图1中的二叉树,后序遍历输出是:9、15、7、20、3
三、三种遍历的递归法
1、二叉树的递归序
首先,我们逐步分析二叉树的递归原理。我们取一个临时指针temp,来在二叉树上行进(根-左-右的顺序),则temp的指向顺序、即二叉树的递归序是:
--START
3(根节点)
9(找到3的左孩子、左子树根节点)
9(找9的左孩子,没有,则回到9)
9(找9的右孩子,没有,则回到9)
3(3的左子树遍历完毕,回到3)
20(3的右子树根节点)
15(20的左孩子)
15(15的左孩子,没有,回到15)
15(15的右孩子,没有,回到15)
20(20的左子树遍历完毕,回到20)
7(20的右孩子)
7(7的左孩子,没有,回到7)
7(7的右孩子,没有,回到7)
20(20的右子树遍历完毕,回到20)
3(3的右子树遍历完毕,回到3)
--END
其中的temp指向其实指的是
上述过程用代码实现如下:
void traversal(TreeNode* root) {//1)程序资源在root节点,判空if (nullptr == root){return;}//2)遍历左子树traversal(root->left);//左子树遍历完成,程序资源回到root节点//3)遍历右子树traversal(root->right);//右子树遍历完成,程序资源回到root节点return;
}
2、三种遍历的递归法实现
则我们可以看见规律。二叉树的递归序中,每一个节点都会被遍历3次。每个节点,当其作为root节点、左子树遍历完成、右子树遍历完成的时候,程序资源都会回到这个节点。
1)先序遍历的递归法
而先序遍历,则只要在第一次处于这个节点的时候进行输出即可。见下列代码:
void preorderTraversal(TreeNode* root) {//根节点为空,直接返回if (nullptr == root){return;}//1)输出cout << root->val << endl;//2)遍历左子树preorderTraversal(root->left);//3)遍历右子树preorderTraversal(root->right);return;
}
2)中序遍历的递归法
同理,中序遍历,只要在递归序的基础上,在第二次回到节点时输出即可。见下列代码:
void inorderTraversal(TreeNode* root) {//根节点为空,直接返回if (nullptr == root){return;}//1)遍历左子树inorderTraversal(root->left);//2)输出cout << root->val << endl;//3)遍历右子树inorderTraversal(root->right);return;
}
3)后序遍历的递归法
同理,后序遍历,只要在递归序的基础上,在第三次回到节点时输出即可。见下列代码:
void postorderTraversal(TreeNode* root) {//根节点为空,直接返回if (nullptr == root){return;}//1)遍历左子树postorderTraversal(root->left);//2)遍历右子树postorderTraversal(root->right);//3)输出cout << root->val << endl;return;
}
这样理解,二叉树的递归遍历法是不是非常简单了?
四、三种遍历的非递归法
任何递归函数都可以改成非递归函数。我们使用的递归法,其实是系统帮助我们压栈的一个过程。
1、分析解决方案
我们知道栈的特性是先入后出,如果按照一般遍历顺序根节点-左孩子-右孩子进行压栈,则和上述遍历顺序不符
2、三种遍历的非递归实现
1)先序遍历实现
算法步骤:
a、根节点进栈;
b、弹出并输出栈顶节点tp;
c、栈顶节点tp的左孩子进栈、右孩子进栈;
d、重复上述b、c;
代码实现:
void preorderTraversal(TreeNode* root) {if (nullptr == root){return;}stack< TreeNode*> mstack;mstack.push(root);while (!mstack.empty()){//打印栈顶节点TreeNode* tp = mstack.top();cout << tp->val << endl;//弹出节点mstack.pop();//右孩子节点压栈if (nullptr != tp->right){mstack.push(tp->right);}//左孩子节点压栈if (nullptr != tp->left){mstack.push(tp->left);}}return;
}
2)中序遍历实现
算法步骤:
a、从根节点开始,整棵树的左边界节点依次进栈;
b、弹出并输出栈顶节点tp;
c、栈顶节点tp的右子树左边界节点依次进栈;
d、重复上述b、c;
代码实现:
void inorderTraversal(TreeNode* root) {TreeNode* tp = root;stack< TreeNode*> mstack;//弹出并输出栈顶节点,并对其右孩子节点压栈while (!mstack.empty() || nullptr != tp){//左边界节点依次进栈if (nullptr != tp){mstack.push(tp);tp = tp->left;}else{//获取栈顶节点指针tp = mstack.top();//输出cout << tp->val << endl;//弹出节点mstack.pop();//如果有右子树,右子树的左边界节点压栈tp = tp->right;}}return;
}
3)后序遍历实现
后序遍历即:左-右-根 的顺序。一般来说,我们一定会先行进到根节点,才能找到其左右子树。所以,我们可以想办法获得 根-右-左的节点遍历,再利用栈的特性反序输出。
算法步骤:
申请两个栈,s1,s2
a、根节点入栈s1;
b、弹出(不输出)栈顶节点tp,压入栈s2;
c、栈顶节点tp的左孩子、右孩子依次进栈s1;
d、重复上述b、c,直到栈s1为空,所有节点进入栈s2;
e、依次弹出并输出栈s2栈顶节点;
代码实现:
void postorderTraversal(TreeNode* root) {//根节点为空,直接返回if (nullptr == root){return;}//申请2个栈stack< TreeNode*> s1, s2;//根节点压入s1s1.push(root);while (!s1.empty()){TreeNode* tp = s1.top();s2.push(tp);s1.pop();if (nullptr != tp->left){s1.push(tp->left);}if (nullptr != tp->right){s1.push(tp->right);}}//依次弹出并输出s2节点while (!s2.empty()){cout << s2.top()->val << endl;s2.pop();}return;
}
二叉树的先序、中序、后序遍历C++相关推荐
- 二叉树的前、中、后序遍历
所谓二叉树遍历是按某种特定规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次.访问结点所做的操作依赖于具体的应用问题. 遍历是二叉树上最重要的运算之一,也是二叉树进行其它运算的基础. 二 ...
- 【数据结构与算法】力扣:二叉树的前、中、后序遍历
递归法 前序遍历 给你二叉树的根节点 root ,返回它节点值的前序 遍历. 示例 1: 输入:root = [1,null,2,3] 输出:[1,2,3] 示例 2: 输入:root = [] 输出 ...
- 二叉树的前、中、后序遍历的代码实现(递归方式)
测试的二叉树的结构 root lfb1 rtb1rtb2 控制台输出的遍历结果 ======从根节点开始,前序遍历此二叉树======= root lfb1 rtb1 rtb2 ======从根节点开 ...
- java中二叉树_Java工程师面试1000题224-递归非递归实现二叉树前、中、后序遍历...
224.使用递归和非递归实现二叉树的前.中.后序遍历 使用递归来实现二叉树的前.中.后序遍历比较简单,直接给出代码,我们重点讨论非递归的实现. class Node { public int valu ...
- 二叉树遍历方法——前、中、后序遍历(图解)
目录 一.前序遍历 (1)递归版本 (2)非递归版本 二.中序遍历 (1)递归版本 (2)非递归版本 三.后序遍历 (1)递归版本 (2)非递归版本 四.总结 五.测试程序 六.程序输出 二叉树的遍历 ...
- 二叉树的前、中、后的非递归遍历
题目 实现一个链式存储的二叉树,采用非递归的形式,按照前.中.后序的顺序遍历二叉树. 代码 /** * 二叉树的前.中.后序的非递归遍历 **/#include <iostream> us ...
- 已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法...
已知一棵二叉树的中序序列和后序序列,写一个建立该二叉树的二叉链表存储结构的算法 #define N 10 //二叉树节点的个数 char postorderstr[]={};//后序序列 char i ...
- 7-10 先序序列创建二叉树,输出先序序列、中序序列、后序序列并输出叶子结点数 (10 分)
7-10 先序序列创建二叉树,输出先序序列.中序序列.后序序列并输出叶子结点数 (10 分) 对于给定的二叉树,输出其先序序列.中序序列.后序序列并输出叶子结点数. 输入格式: 二叉树的先序遍历序列. ...
- 二叉树的构造(前序+中序)---(后序 + 中序)
二叉树的构造(前序+中序)-(后序 + 中序) 思路:要对前序+中序(后序+中序)的构建树的动态过程要了解,思路比较简单,在了解了这个过程之后,理解下面代码就容易了. 过程 参考图: 前序 + 中序: ...
- 先序序列和中序序列构造二叉树,中序序列和后序序列构造二叉树
1:首先读者要了解二叉树BinaryTree基本概念,其次区分左子树与左孩子节点,右子树与右孩子节点.(在数据结构中 一个节点可以成为一棵树,对于没有孩子节点的节点称为为叶子节点). 2:在 ...
最新文章
- SQLAlchemy技术文档(中文版)(中)
- 推荐系统中的召回算法--协同过滤
- 学习打卡-2018/08/09
- 是否要入坑强化学习,看了这篇文章再说
- GDI+中常见的几个问题(6)
- 隐藏键盘_三星新专利:带有隐藏键盘的三折叠屏手机
- php - MySQL创建新用户并授权
- 说说python程序的执行过程_做人,尽量不要说这四种话,一说,祸事就来了
- 知乎推荐算法工程师面经
- 技术·融合·治理|众享链网试运行总结暨正式运行发布会预告
- Google推出一款用户隐私保护工具箱
- 和平精英体验服服务器更新维护什么意思,和平精英8月9日体验服官方申请地址 和平精英更新6项内容需要多注意!和平精英8月9日更新时间确定...
- STC学习:光照报警器
- 341.扁平化嵌套列表迭代器
- 硬盘录播服务器,高清录播主机录播服务器HT-7500_航天广电录播系统设备
- PDFjs的使用说明书
- 商标注册流程和周期是什么
- VS2019 测试使用libusb
- 20135203齐岳 信息安全系统设计基础第四周学习总结
- java dozer_java – Dozer双向映射(String,String)与自定义转换器不可能?
热门文章
- 虫儿飞计算机音乐,虫儿飞 MIDI File Download :: MidiShow
- XXXX项目可实施性报告
- HSDPA、WiMAX和LTE关键技术比较与分析
- 响应式中小学早教教育机构类网站源码 HTML5教育培训机构网站织梦模板
- 【C语言】职工管理系统详解(文件操作)
- 关于NTFS与FAT32的互相转化
- 2020年中国家居建材行业发展规模及家居重点企业对比分析:顾家家居vs曲美家居[图]
- 基于二分查找的抽签游戏算法的优化
- 从零开始搭建个人网页II-前端部分
- 大学英语计算机等级考试,全新版大学英语综合教程3课文原文及翻译6-8,全国计算机等级考试一级试题及答案(25套).doc...