当前位置:网站首页>Binary tree non-recursive traversal
Binary tree non-recursive traversal
2022-07-31 22:11:00 【Massachusetts_11】
1. 遍历一棵树
前、中、The path of the post-order traversal is actually the same,They all travel the same way.
前、中、The results of post-order access are different,In fact, the timing of accessing the nodes is different:
前序:Visit a node as soon as you encounter it
中序:After visiting the left tree, go to visit
后序:After visiting the right subtree, visit again
如下是B节点的前、中、Post-order access timing
2. 非递归遍历
2.1 理解
The previous recursive traversal,Think of a tree as a symmetrical structure:左子树
根右子树
,With the help of recursive functions,You can enter the left and right subtrees for access;
But if you want to do it within the current function迭代访问,The previous left-right subproblem approach is difficult to implement.
Here we might as well take a look at the path graph of this traversal:
Walk down the far left firstA-B-D
然后向上,走D的右子树、B的右子树、A的右子树,走完AThe return of the right subtree means the traversal is over
Here access to the right subtree can be regarded as one子问题——Visit another tree rooted at the right node,Go back to the beginning;
It can be found that the order in which the nodes on the left go for the first time is from top to bottom:A-B-D
,The order in which the right subtree is visited at the next encounter is againD-B-A
,恰好相反,因此可以用栈的结构,When walking from the left, first save the nodes from top to bottom,When traversing to the end,When it is empty, remove the node at the top of the stack,Use this node to access its right tree;
At the same time by virtue of the stack structure,When entering the right tree,Go to the node of the right tree,Still into this stack,When the right tree is finished walking back,All the pushed nodes of the right tree have also been taken out,Again, only the nodes on the previous trunk are left,Mainline logic can also continue,Similar to the logic of the recursive way——No matter how complicated the logic of recursion is,Complete the branch task and come back,My main quest is still going on as normal.
2.2 实现
注:The following only provides methods for traversing the entire tree non-recursively,前、中、The timing of subsequent access to the node is not written,具体见后.
变量定义:
实现:
Traverse the leftmost node,At the same time, they are pushed onto the stack in turn
Start fetching elements from the stack
Access its right tree through this node
The judgment of the end of the traversal
- The elements in the stack are fetched——栈空
- At the same time, the current root node corresponds to an empty tree
The case where the subtree is empty(Back to the main question):
Skip the traversal of the current tree,Take the next node from the stack
The current logic just works
3. 前、中、后序遍历
前、中、The only difference between post-order traversal is the timing of visiting nodes
Each node can be seen as being traversed three times:first encounter,Come back from the left and meet again,Meet again after traversing the right subtree,
These three encounters happened to correspond to the previous ones、中、subsequent access timing,
Just find the corresponding parts of these three encounters in the iterative logic to visit,before you can finish、中、后序遍历.
3.1 前序遍历
访问时机:第一次碰到,That is, when the left traversal is to be pushed into the stack

此时访问,You can put it on the stack.
vector<int> preorderTraversal(TreeNode* root)
{
vector<int> v;//Storage accesses out elements
stack<TreeNode*> st;//栈——Temporary storage node
TreeNode* cur = root;//A pointer for traversing the entire tree
while (!st.empty() || cur)
{
//Traverse all leftmost nodes of the current tree
while (cur)
{
v.push_back(cur->val);
st.push(cur);
cur = cur->left;
}
//取出栈顶节点
TreeNode* tmp = st.top();
st.pop();
//前序遍历右树
cur = tmp->right;//更新rootis the right tree of the top node of the stack
}
return v;
}
3.2 中序遍历
访问时机:Left node access is complete,节点出栈,It's about time to enter the right tree for access
此时访问,You can put it on the stack.
vector<int> inorderTraversal(TreeNode* root)
{
vector<int> v;//Storage accesses out elements
stack<TreeNode*> st;//栈——Temporary storage node
TreeNode* cur = root;//A pointer for traversing the entire tree
while (!st.empty() || cur)
{
//Traverse all leftmost nodes of the current tree
while (cur)
{
st.push(cur);
cur = cur->left;
}
//取出栈顶节点
TreeNode* tmp = st.top();
st.pop();
v.push_back(cur->val);
//前序遍历右树
cur = tmp->right;//更新rootis the right tree of the top node of the stack
}
return v;
}
3.3 后序遍历
Access is done on the entire right tree,Visit when you come back to this node again
Since accessing the right tree is an iterative traversal of multiple layers,The location of the visit cannot be found directly on this single code
观察后,The last node visited in the postorder traversal of the right subtree is the root node of the right tree,The next node after visiting this node is the node to be visited currently

So visit one node at a time,This node is recorded,Before a node is popped from the stack, it must first determine whether the right node corresponding to the top node of the stack is a recorded node
- 若是,则出栈并进行访问,同时Update the node for logging,The right tree does not need to be visited at this time,Direct access to the next top element of the stack
- Otherwise, it indicates that it is currently②的位置,先不出栈,先访问右树,The right tree comes back and pops the stack again
**特殊情况:**When the right tree is empty,This node is also visited

如访问BWhen the right tree is finished,prev
是D,但此时Balso have to visit,Therefore, if the right tree is empty, the judgment condition for pop-up access should also be added
vector<int> postorderTraversal(TreeNode* root)
{
vector<int> v;//Storage accesses out elements
stack<TreeNode*> st;//栈——Temporary storage node
TreeNode* cur = root;//A pointer for traversing the entire tree
TreeNode* prev = nullptr;
while (!st.empty() || cur)
{
//Traverse all leftmost nodes of the current tree
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;//The next loop directly accesses the next node in the stack as the empty tree
}
else
{
cur = tmp->right;//更新rootis the right tree of the top node of the stack
}
}
return v;
}
边栏推荐
- Chapter Six
- [Code Hoof Set Novice Village 600 Questions] Merge two numbers without passing a character array
- PCB stackup design
- Efficient Concurrency: A Detailed Explanation of Synchornized's Lock Optimization
- Recognize anomalies (you will understand after reading this)
- 每月一书(202207):《Swift编程权威指南》
- Talking about the algorithm security of network security
- Bika LIMS open source LIMS set - use of SENAITE (detection process)
- ReentrantLock原理(未完待续)
- Go1.18 upgrade function - Fuzz test from scratch in Go language
猜你喜欢
GateWay implements load balancing
登录业务实现(单点登录+微信扫码+短信服务)
财务盈利、偿债能力指标
Judging decimal points and rounding of decimal operations in Golang
第七章
基于STM32 环形队列来实现串口接收数据
高通cDSP简单编程例子(实现查询高通cDSP使用率、签名),RK3588 npu使用率查询
Redis Overview: Talk to the interviewer all night long about Redis caching, persistence, elimination mechanism, sentinel, and the underlying principles of clusters!...
MATLAB program design and application 2.4 Common internal functions of MATLAB
focus on!Haitai Fangyuan joins the "Personal Information Protection Self-discipline Convention"
随机推荐
利用反射实现一个管理对象信息的简单框架
A few permanent free network transmission, convenient and simple (Intranet through tutorials)
LevelSequence source code analysis
Shell 脚本 快速入门到实战 -02
Dry goods | 10 tips for MySQL add, delete, change query performance optimization
架构实战营模块八作业
PCB stackup design
角色妆容的实现
find prime numbers up to n
「APIO2010」巡逻 题解
Qualcomm cDSP simple programming example (to query Qualcomm cDSP usage, signature), RK3588 npu usage query
C#中引用类型的变量做为参数在方法调用时加不加 ref 关键字的不同之处
Commonly used security penetration testing tools (penetration testing tools)
了解下C# 匿名方法
【核心概念】图像分类和目标检测中的正负样本划分以及架构理解
[QNX Hypervisor 2.2用户手册]9.14 set
Go1.18 upgrade function - Fuzz test from scratch in Go language
Basic configuration of OSPFv3
Financial profitability and solvency indicators
【AcWing】The 62nd Weekly Match 【2022.07.30】