当前位置: 首页 > news >正文

二叉树的中序&后序遍历——非递归版本

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;}
};

 


http://www.mrgr.cn/news/43469.html

相关文章:

  • 【C语言】分支与循环
  • 矩阵求解复数(aniwoth求解串扰)
  • 基金好书入门阅读笔记《基金作战笔记:从投基新手到配置高手的进阶之路》1
  • mybatis分页拦截器
  • 基于H3C环境的实验——OSPF
  • 字节跳动收购Oladance耳机:强化音频技术,加速VR/AR生态布局
  • 华为OD机试 - 基站维护工程师数 - 动态规划(Python/JS/C/C++ 2024 E卷 200分)
  • Python水循环标准化对比算法实现
  • CART 回归树中的公式详细讲解
  • 设计模式-创建型-常用:单例模式、工厂模式、建造者模式
  • Codeforces Beta Round 14 (Div. 2) E. Camels (DP)
  • 如何解决 MySQL ERROR 1040 (08004): Too many connections ?
  • 企业必备:搭建大模型应用平台实操教程
  • 算法题总结(七)——哈希表
  • 【LLM】OpenAI o1模型和相关技术
  • 数据结构的组成:构建高效算法的基础
  • 10.5二分专练,二分边界情况,+1不加1的判断,方向判断,各种DEBUG
  • c基础面试题
  • 业务能力技术栈 —— 流量卡
  • class 004 选择 冒泡 插入排序