二叉树的迭代遍历

144. 二叉树的前序遍历
145. 二叉树的后序遍历
94. 二叉树的中序遍历

二叉树的迭代遍历,也就是非递归遍历。思想就是利用栈存储节点,当访问的时候从栈弹出。

前序遍历

前序遍历的顺序是中左右,先将根节点的值放进数组中,再依次将右孩子、左孩子入栈,这样才能保证下次栈顶弹出的是上个节点的左孩子。

这里有两个操作:

  1. **处理:**将节点的数值放入数组中;
  2. **访问:**遍历节点。

注意:前序遍历的这两个操作顺序是先处理完后访问的。

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != nullptr)    
            st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->right != nullptr)
                st.push(node->right);
            if (node->left != nullptr)
                st.push(node->left);
        }
        return result;
    }
};

中序遍历

中序遍历的顺序是左中右,跟前序遍历很大的不同是,那两步操作的顺序变为了访问、处理、再访问,也就会导致用上面相似的代码不能完成中序遍历。所以这里需要用一个指针来遍历节点,用栈来处理节点。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != nullptr || !st.empty()) {
            if (cur != nullptr) {
                st.push(cur);
                cur = cur->left;
            } else {
                cur = st.top();
                st.pop();
                result.push_back(cur->val);
                cur = cur->right;
            }
        }
        return result;
    }
};

后序遍历

后序遍历的顺序是左右中,跟前序遍历很相似,两部操作的顺序是先访问后处理,所以再前序遍历的基础上稍稍改动就OK了。

先序遍历是中左右,改变代码的左右入栈顺序后就变为中右左,再reverse逆置一下就变为后序遍历的左右中了。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != nullptr)
            st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left != nullptr)
                st.push(node->left);
            if (node->right != nullptr) 
                st.push(node->right);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

这里补充前、中、后序的另外一种遍历方式

前序遍历

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != nullptr || !st.empty()) {
            while (cur != nullptr) {
                result.push_back(cur->val);
                st.push(cur);
                cur = cur->left;
            }
            cur = st.top();
            st.pop();
            cur = cur->right;
        }
        return result;
    }
};

中序遍历

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != nullptr || !st.empty()) {
            while (cur != nullptr) {
                st.push(cur);
                cur = cur->left;
            }
            cur = st.top();
            st.pop();
            result.push_back(cur->val);   
            cur = cur->right;
        }
        return result;
    }
};

后序遍历

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != nullptr || !st.empty()) {
            while (cur != nullptr) {
                result.push_back(cur->val);
                st.push(cur);
                cur = cur->right;
            }
            cur = st.top();
            st.pop();
            cur = cur->left;
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

以上的两种后序遍历都有一点不好,就是遍历的过程并不是后序,只是结果是后序遍历,所以这里给出另一种后序遍历方式。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* prev = nullptr;
        while (cur != nullptr || !st.empty()) {
            while (cur != nullptr) {
                st.push(cur);
                cur = cur->left;
            }
            TreeNode* top = st.top();
            if (top->right == nullptr || top->right == prev) {
                result.push_back(top->val);
                st.pop();
                prev = top;
            } else {
                cur = top->right;
            }
        }
        return result;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云朵c

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值