二叉树的中序&后序遍历——非递归版本
创作时间:
作者:
@小白创作中心
二叉树的中序&后序遍历——非递归版本
引用
CSDN
1.
https://m.blog.csdn.net/2301_80689220/article/details/142718189
二叉树的遍历是数据结构中的一个重要知识点,其中中序遍历和后序遍历是两种常见的遍历方式。本文将详细介绍这两种遍历方式的非递归实现方法,帮助读者更好地理解二叉树的遍历过程。
1.题目解析
题目来源:二叉树的中序遍历——力扣
测试用例
题目来源:二叉树的后序遍历——力扣
测试用例
2.算法原理
中序遍历
中序遍历:左子树->根节点->右子树
与之前前序遍历的思路基本相同,不过需要注意的是中序变量需要在遍历完左子树后才可以访问根节点,也就是首先将左子树入栈,入栈完成后取出栈顶结点再访问该节点,这样就可以达到先访问左子树再访问根节点再访问右子树的效果
后序遍历
后序遍历:左子树->右子树->根节点
后序遍历属于三个遍历中最难的一种,因为我们需要先遍历左子树再遍历右子树后才能访问根节点,这并不是简单的将前序遍历逆置就可以得到的,首先我们有以下的困难:
1. 当访问一个节点首先将其左子树入栈后如何将其右子树入栈后再访问根节点
2.如何判断是否需要访问一个节点的右子树才能避免重复访问
3.如何控制入栈的顺序
解决方法:
1.首先我们从一棵树的根节点开始,不断向栈内插入左节点直到左边无可插入元素,此时处理栈顶元素,我们首先要判断此元素是否有右子树,有则需要入栈,反之没有则访问该节点的上一个级节点,这里判断的方法是创建一个prev保留待判断节点的栈内上一个元素,如果该元素是待判断元素的右节点则代表待判断元素的左右子树均已遍历,直接访问该节点即可
2.如果prev不是待判断元素的上一个节点则表示此时待判断节点的右子树还没有遍历,需要访问其右子树,所以将栈顶元素的右节点放入循环即可
3.实战代码
中序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> v;
stack<TreeNode*> st;
TreeNode* cur = root;
while(cur || !st.empty())
{
//只入栈根节点而不访问
while(cur)
{
st.push(cur);
cur = cur->left;
}
TreeNode* top = st.top();
st.pop();
//在左子树访问完毕之后再访问根节点
//以达到左子树->根节点->右子树的顺序
v.push_back(top->val);
cur = top->right;
}
return v;
}
};
后序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root)
{
TreeNode* prev = nullptr;
stack<TreeNode*> st;
vector<int> v;
TreeNode* cur = root;
while(cur || !st.empty())
{
while(cur)
{
st.push(cur);
cur = cur->left;
}
TreeNode* top = st.top();
//首先判断栈顶结点右子树是否为空或者之前已经访问过该节点的右子树
//如果是则直接入到v中后在栈中删除该元素,并且将该节点更新为prev节点
if(top->right == nullptr || top->right == prev)
{
v.push_back(top->val);
st.pop();
prev = top;
}
//如果没有访问过说明只是访问了之前节点的左子树
//需要先访问右子树再访问该节点
else
{
cur = top->right;
}
}
return v;
}
};
热门推荐
2024年法考主观题合格分全国一样吗?合格标准分是多少
张澜涛|古代经典神话故事魅力永在
蓝氏贾第鞭毛虫治疗药物
常见艾灸穴位及其功效与施灸方法详解
可复性牙髓炎的治疗方法
牙髓炎不治疗会怎么样
如何理解期货市场的交易策略?不同市场环境下的投资逻辑是什么?
立春邂逅赵州桥
影响钕铁硼磁钢性能的因素及方法
15 部靠出色世界观设定挽救的烂片,仅靠世界观设定能 “续命”吗?
心理学真相:自卑与缺乏安全感的背后,常隐匿着心灵深处童年创伤
助焊膏的分类与使用方法
新加坡本科预科入读条件详解
长江存储“借壳”疑云散去,万润科技股价何去何从?
别让乙肝“赖上”你:预防秘籍大公开
手机号黑名单怎么解除?遇到误拦截如何快速恢复?
肾移植术前如何组织配型
巴西木是水培好还是土培好呢?
饮食调节免疫功能的原因
郄门穴——心脏疾病急救穴
摩托车驾照考试全解析:一文看懂准驾车型与考试体系
2024年中国金属采矿行业竞争格局及市场份额分析
分手后如何判断对方是否已经放下了自己?
红薯吃多了会便秘吗
糕点霉菌污染防控措施
离地间隙最大的10款中大型SUV
拉丁美洲历史专业简介
左肺上叶尖后段磨结节5mm严重吗
9年随访揭示肺磨玻璃结节风险评估新视角:从病例解析看早期肺癌诊疗策略
小米手机NFC功能的开启方法与注意事项