Leetcode 102/144/145 二叉樹的前/中/後序遍歷,迭代寫法模板(C++)

今天在刷Leetcode的二叉樹卡片,首先碰到的就是二叉樹的三種遍歷方法,遞歸方法很簡單,但是要求用迭代的方法來寫的話就沒那麼容易了,在題解區裏看到了一個大神的模板化迭代寫法,非常有新意,於是在這裏寫點自己的理解

原文鏈接如下:

https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/miao-sha-quan-chang-ba-hou-lang-by-sonp/

理論上來說,所有遞歸的算法都是可以用非遞歸來實現的,因爲遞歸本身就是操作系統調用棧來保存函數的入口地址,遇到return之後返回到入口,因此用非遞歸方法寫遞歸程序最核心的部分就是

1. 如何“保護現場”,在二叉樹的遍歷這裏,原答案用到了一個nullptr空指針來保存當前訪問但又不輸出的那個節點(下面代碼中的temp節點),也就是說,第二次遇到同一個節點的時候,意味着這個節點的前驅已經遍歷過了,因此可以放心大膽地輸出當前節點的value

2. 由於棧是FILO先進後出的結構,這就跟遞歸的順序要相反,也就是說我們正常後序遍歷的順序是 left->right->mid,在棧這裏就要mid->right->left的順序入棧,出棧的時候才能按照正常遞歸的順序

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if(!root) return {};
        vector<int>ans;
        stack<TreeNode*>mystack;            //用棧來保存遍歷的節點
        mystack.push(root);
        while(!mystack.empty())
        {
            auto temp = mystack.top();
            mystack.pop();
            if(temp)
            {
                mystack.push(temp);            //此題爲後序遍歷,因此入棧順序要反過來,爲中->左->右
                mystack.push(nullptr);
                if(temp->right) mystack.push(temp->right);
                if(temp->left) mystack.push(temp->left);
            }
            else
            {
                ans.push_back(mystack.top()->val);
                mystack.pop();
            }
        }
        return ans;

    }
};

上面是本人蔘照鏈接自己寫的後序遍歷的一個案例,先序遍歷和中序遍歷只需要將if(temp)裏的入棧順序作相應調整即可

 

另外此類題還有官方題解提到的莫里斯遍歷,核心的部分也是確認當前節點的前驅是否已遍歷,實現O(1)的空間複雜度,這裏先佔個坑,後面自己看懂了再來寫感想

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章