当前位置:网站首页>二叉树非递归遍历
二叉树非递归遍历
2022-07-31 21:33:00 【Massachusetts_11】
1. 遍历一棵树
前、中、后序遍历的路径实际是相同的,都是以如上路径去游历。
前、中、后序访问的结果不同,实际是访问节点的时机不同:
前序:一遇到节点就去访问
中序:访问完左树再去访问
后序:访问完右子树再去访问
如下是B节点的前、中、后序访问时机
2. 非递归遍历
2.1 理解
之前的递归遍历,将一棵树看成一个对称结构:左子树
根右子树
,借助递归函数,可以进入左右子树进行访问;
但如果想在当前函数内进行迭代访问,之前的左右子问题的方式就很难实现了。
这里我们不妨再看看这个遍历的路径图:
首先沿着最左侧向下走过A-B-D
然后向上,走D的右子树、B的右子树、A的右子树,走完A的右子树回来就代表遍历结束了
这里访问右子树就可以看成是一个子问题——访问以右节点为根的另一棵树,重新回到最一开始;
可以发现左侧节点第一次走到的顺序是从上至下:A-B-D
,下一次遇到访问右子树的顺序又是D-B-A
,恰好相反,因此可以用栈的结构,从左侧走的时候先把节点依次从上至下存起来,当遍历到底,遇到空的时候再取出栈顶的节点,通过这个节点去访问它的右树;
同时凭借着栈的结构,当进入右树,走到右树的节点,依然入此栈,当右树走完回来,右树所有入栈的节点也都已经取出,又只剩下了之前主干上的节点,还可继续主线逻辑,与递归方式的逻辑相似——不管递归出去的逻辑多复杂,完成了分支任务回来,我的主线任务还要正常进行。
2.2 实现
注:以下只提供了非递归游历整棵树的方法,前、中、后序访问节点的时机未写入,具体见后。
变量定义:
实现:
遍历最左侧节点,同时将他们依次入栈
开始取栈中元素
通过此节点访问它的右树
遍历结束的判断
- 栈中元素取完——栈空
- 同时当前的根节点对应一棵空树
子树为空的情况(返回主干问题):
跳过当前树的遍历,从栈中取下一个节点
当前逻辑刚好可以实现
3. 前、中、后序遍历
前、中、后序遍历唯一的区别就是访问节点的时机不同
每个节点可以看成是有三次被经过:到达初遇,从左边回来再遇,遍历完右子树再遇,
这三次相遇恰好就对应前、中、后序的访问时机,
只需在迭代逻辑中找到这三次相遇的对应部分进行访问,即可完成前、中、后序遍历。
3.1 前序遍历
访问时机:第一次碰到,也就是左侧遍历要入栈的时候

此时访问,进行入栈即可。
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> v;//存储访问出元素
stack<TreeNode*> st;//栈——临时储存节点
TreeNode* cur = root;//用于游历整棵树的指针
while (!st.empty() || cur)
{
//遍历当前树的所有最左侧节点
while (cur)
{
v.push_back(cur->val);
st.push(cur);
cur = cur->left;
}
//取出栈顶节点
TreeNode* tmp = st.top();
st.pop();
//前序遍历右树
cur = tmp->right;//更新root为栈顶节点的右树
}
return v;
}
3.2 中序遍历
访问时机:左侧节点访问已完成,节点出栈,马上要进入右树进行访问的时候
此时访问,进行入栈即可。
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> v;//存储访问出元素
stack<TreeNode*> st;//栈——临时储存节点
TreeNode* cur = root;//用于游历整棵树的指针
while (!st.empty() || cur)
{
//遍历当前树的所有最左侧节点
while (cur)
{
st.push(cur);
cur = cur->left;
}
//取出栈顶节点
TreeNode* tmp = st.top();
st.pop();
v.push_back(cur->val);
//前序遍历右树
cur = tmp->right;//更新root为栈顶节点的右树
}
return v;
}
3.3 后序遍历
在整棵右树访问完成,再次回到这个节点的时候进行访问
由于访问右树是一个多层的迭代遍历,无法在这个单次的代码上直接找到访问的位置
观察后,右子树进行后序遍历的最后一个访问的节点是右树的根节点,访问完这个节点的下一个节点就是当前要访问的节点

所以每次访问完一个节点,都将这个节点进行记录,节点要出栈都先判断栈顶节点对应的右节点是否为已记录节点
- 若是,则出栈并进行访问,同时更新用于记录的节点,此时右树无需访问,直接访问下一个栈顶元素
- 否则说明当前是②的位置,先不出栈,先访问右树,右树回来再出栈
**特殊情况:**当右树为空,这个节点也要访问

如访问B的右树完时候,prev
是D,但此时B也得进行访问,所以右树为空也要加入出栈访问的判断条件
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> v;//存储访问出元素
stack<TreeNode*> st;//栈——临时储存节点
TreeNode* cur = root;//用于游历整棵树的指针
TreeNode* prev = nullptr;
while (!st.empty() || cur)
{
//遍历当前树的所有最左侧节点
while (cur)
{
st.push(cur);
cur = cur->left;
}
TreeNode* tmp = st.top();
if (tmp->right == prev || tmp->right == nullptr)
{
st.pop();
v.push_back(tmp->val);
prev = tmp;
cur = nullptr;//下一次循环直接当空树访问下一个栈中节点
}
else
{
cur = tmp->right;//更新root为栈顶节点的右树
}
}
return v;
}
边栏推荐
- What is Thymeleaf?How to use.
- Several methods for deleting specified elements in Golang slices
ojdbc8 "Recommended Collection"- What's wrong with the sql syntax in my sql
- 每月一书(202207):《Swift编程权威指南》
- 顺序表的实现
- Teach you how to deploy Nestjs projects
- Shell script quick start to actual combat -02
- ThreadLocal
- sqlite3 simple operation
猜你喜欢
Apache EventMesh distributed event-driven multi-runtime
顺序表的实现
Write a database document management tool based on WPF repeating the wheel (1)
Architecture Battalion Module 8 Homework
[NLP] What is the memory of the model!
Efficient Concurrency: A Detailed Explanation of Synchornized's Lock Optimization
ECCV 2022 Huake & ETH propose OSFormer, the first one-stage Transformer framework for camouflaging instance segmentation!The code is open source!...
Implementing a Simple Framework for Managing Object Information Using Reflection
Recognize anomalies (you will understand after reading this)
The old music player WinAmp released version 5.9 RC1: migrated to VS 2019, completely rebuilt, compatible with Win11
随机推荐
find prime numbers up to n
Commonly used security penetration testing tools (penetration testing tools)
How to debug TestCafe
Verilog implements a divide-by-9 with a duty cycle of 5/18
In Golang go-redis cluster mode, new connections are constantly created, and the problem of decreased efficiency is solved
ThreadLocal
C language parsing json string (json object is converted to string)
基于STM32 环形队列来实现串口接收数据
UserAgent resolution
Teach you how to deploy Nestjs projects
idea中搜索具体的字符内容的快捷方式
Several methods for deleting specified elements in Golang slices
Memblaze released the first enterprise-grade SSD based on long-lasting particles. What is the new value behind it?
Audio alignment using cross-correlation
"The core concept of" image classification and target detection in the positive and negative samples and understanding architecture
【核心概念】图像分类和目标检测中的正负样本划分以及架构理解
Made with Flutter and Firebase!counter application
架构实战营模块 8 作业
C程序设计-方法与实践(清华大学出版社)习题解析
Financial profitability and solvency indicators