文章目录
- [1. 前序遍历](#1. 前序遍历)
- [2. 中序遍历](#2. 中序遍历)
- [3. 后序遍历](#3. 后序遍历)
1. 前序遍历
前序遍历,顺序为根左右 ,因此在借助栈 的非递归实现中,可以立即访问,因此前序遍历的非递归写法是较为简单的。需要注意的是,栈先进后出的顺序,因此左子树,右子树的访问顺序,入栈时,应先入右子树,再入左子树。
LEETCODE 链接
cpp
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
using node = TreeNode;
stack<node*> st;
vector<int> ret;
if(root)
st.push(root);
while(st.size()) {
node* cur = st.top();
st.pop();
ret.push_back(cur->val);
if(cur->right)
st.push(cur->right);
if(cur->left)
st.push(cur->left);
}
return ret;
}
};
2. 中序遍历
中序遍历顺序为左根右 ,因此当前结点不能立刻记录访问 ,而应该确保左子树穷尽后,再记录该结点,然后再对该结点的右子树进行中序遍历 。中序遍历非递归写法,相较于前序遍历,略微复杂,因为要先记录访问左子树后,方能记录当前结点。
LEETCODE 链接
cpp
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
vector<int> ret;
stack<TreeNode*> st;
TreeNode* cur = root;
while(st.size() || cur) {
while(cur) {
st.push(cur);
cur = cur->left;
}
TreeNode* node = st.top();
st.pop();
ret.push_back(node->val);
cur = node->right;
}
return ret;
}
};
3. 后序遍历
后序遍历的顺序为左右根 ,后序遍历是最为复杂的,因为当前结点的访问,必须在当前结点的左子树和右子树都访问后,才能访问记录。
下面,介绍一种巧妙直观的迭代写法 。后序遍历顺序为左右根 ,将遍历访问结果反转,即为根右左 ,实质近似于前序遍历的根左右 ,即迭代写法一致,仅需调整左右子树根结点入栈顺序即可 ,最后将得到的结果做反转 ,即为最终结果。
LEETCODE 链接
cpp
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
using node = TreeNode;
vector<int> ret;
stack<node*> st;
if(root)
st.push(root);
while(st.size()) {
node* cur = st.top();
st.pop();
ret.push_back(cur->val);
if(cur->left)
st.push(cur->left);
if(cur->right)
st.push(cur->right);
}
ranges::reverse(ret);
return ret;
}
};