二叉树的迭代遍历
二叉树的递归遍历是比较简单的
- 前序
- 中序
- 后序
前序遍历
前序遍历代码如下:
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
preorder(root,res);
return res;
}
void preorder(TreeNode* cur, vector<int> &res){
if (cur == nullptr)return;
res.push_back(cur->val);
preorder(cur->left,res);
preorder(cur->right,res);
}
};
而中序遍历、后序遍历只需要改一下访问的顺序就可以。
但是迭代写法却少有人会写。
比如这里使用迭代写前序遍历是这样的。
class Solution {
public:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if(!root)return res;
st.push(root);
while(!st.empty()){
TreeNode* cur = st.top();st.pop();
res.push_back(cur->val);
if(cur->right) st.push(cur->right);
if(cur->left) st.push(cur->left);
}
return res;
}
};
这里首先创建一个栈st来实现,而注意的是进入栈的顺序是先进右节点再进左节点,这样出栈的顺序便是中左右,符合前序遍历的顺序。
而中序遍历却不可以只改几行代码就实现了。
中序遍历
原因是因为:在前序遍历中,访问和处理元素的顺序是一致的,这里的访问指遍历到这个元素,处理指的是将其放进数组里。而在中序遍历中,访问后还不能处理,要到达最后左节点为空后,再将左节点处理!具体流程如下:
因此我们需要借助指针遍历来实现,代码如下:
class Solution {
public:
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*> st;
vector<int> res;
TreeNode* cur = root;
while(cur!=nullptr || !st.empty()){
if(cur != nullptr){
st.push(cur);
cur = cur->left; // 左
}else
{
cur = st.top();st.pop();
res.push_back(cur->val);
cur = cur->right; // 右
}
}
return res;
}
};
后序遍历
后序遍历本质上和前序遍历是极其相似的,而且其访问和处理都是在同一时刻,因此可以改一下前序遍历的代码。
如果我们改变结点进入的顺序就会从中左右 -> 中右左,这个时候我们只需再反转一下数组即可。
代码如下:
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> res;
stack<TreeNode*> st;
if(root == nullptr)return res;
st.push(root);
while(!st.empty()){
TreeNode* cur = st.top();st.pop();
res.push_back(cur->val);
if(cur->left) st.push(cur->left);
if(cur->right) st.push(cur->right);
}
reverse(res.begin(),res.end());
return res;
}
};