算法-二叉樹前序遍歷的思考

有兩種通用的遍歷樹的策略:

    深度優先搜索(DFS)

    在這個策略中,我們採用深度作爲優先級,以便從跟開始一直到達某個確定的葉子,然後再返回根到達另一個分支。

    深度優先搜索策略又可以根據根節點、左孩子和右孩子的相對順序被細分爲前序遍歷,中序遍歷和後序遍歷。

    寬度優先搜索(BFS)

    我們按照高度順序一層一層的訪問整棵樹,高層次的節點將會比低層次的節點先被訪問到。

作者:LeetCode
鏈接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/solution/er-cha-shu-de-qian-xu-bian-li-by-leetcode/

 

 


2 public: 3 vector<int> res; 4 vector<int> preorderTraversal(TreeNode* root){ 5 if(root){ 6 res.push_back(root -> val); 7 preorderTraversal(root -> left); 8 preorderTraversal(root -> right); 9 }return res; 10 } 11 };

這個就算公共變量,可以直接用。

我的輸入
[1,null,2,3]
我的答案
[1,2,3]
 1 class Solution {
 2 public:
 3     vector<int> preorderTraversal(TreeNode* root){
 4     vector<int> res;
 5         if(root){
 6             res.push_back(root -> val);
 7             preorderTraversal(root -> left);
 8             preorderTraversal(root -> right);
 9         }return res; 
10     }
11 };

這個res就是局部變量,輸入0,null,1,2 輸出就是1,而沒有其他值。

這屬於程序接口問題,preorderTraversal(TreeNode* root){}相當於一個函數,裏面的內容算是臨時變量,所以只有一個值出來。

再來改進
首先 遍歷可以不用遞歸 ( 比如莫里斯遍歷 )這樣能提高效率
如果用遞歸可以搞兩個函數 外部函數聲明臨時變量 然後內部函數每次往這個臨時變量裏面push 這樣就行了

/**
 * 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> ret;
    vector<int> preorderTraversal(TreeNode* root) {
        pre_travel(root);
        return ret;
    }
    void pre_travel(TreeNode* root)
    {
        if(root)//當前結點非空
        {
            ret.push_back(root->val);//訪問根節點
            pre_travel(root->left);//遞歸左子樹
            pre_travel(root->right);//遞歸右子樹
        }
    }
};

 再就是,遞歸的本質其實可以理解成棧。    遞歸的本質就是壓棧,瞭解遞歸本質後就完全可以按照遞歸的思路來迭代。
    怎麼壓,壓什麼?壓的當然是待執行的內容,後面的語句先進棧,所以進棧順序就決定了前中後序。

我們需要一個標誌區分每個遞歸調用棧,這裏使用nullptr來表示。
具體直接看註釋,可以參考文章最後“和遞歸寫法的對比”。先序遍歷看懂了,中序和後序也就秒懂。

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

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;  //保存結果
        stack<TreeNode*> call;  //調用棧
        if(root!=nullptr) call.push(root);  //首先介入root節點
        while(!call.empty()){
            TreeNode *t = call.top();
            call.pop();  //訪問過的節點彈出
            if(t!=nullptr){
                if(t->right) call.push(t->right);  //右節點先壓棧,最後處理
                if(t->left) call.push(t->left);
                call.push(t);  //當前節點重新壓棧(留着以後處理),因爲先序遍歷所以最後壓棧
                call.push(nullptr);  //在當前節點之前加入一個空節點表示已經訪問過了
            }else{  //空節點表示之前已經訪問過了,現在需要處理除了遞歸之外的內容
                res.push_back(call.top()->val);  //call.top()是nullptr之前壓棧的一個節點,也就是上面call.push(t)中的那個t
                call.pop();  //處理完了,第二次彈出節點(徹底從棧中移除)
            }
        }
        return res;
    }
};        //先序遍歷
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> call;
        if(root!=nullptr) call.push(root);
        while(!call.empty()){
            TreeNode *t = call.top();
            call.pop();
            if(t!=nullptr){
                call.push(t);  //在右節點之前重新插入該節點,以便在最後處理(訪問值)
                call.push(nullptr); //nullptr跟隨t插入,標識已經訪問過,還沒有被處理
                if(t->right) call.push(t->right);
                if(t->left) call.push(t->left);
            }else{
                res.push_back(call.top()->val);
                call.pop();
            }
        }
        return res;   
    }
};

後序遍歷
void dfs(t){ //進入函數表示“訪問過”,將t從棧中彈出

    dfs(t->left);   //因爲要訪問t->left, 所以我先把函數中下面的信息都存到棧裏。
                //依次call.push(t->right), call.push(t)【t第二次入棧】, call.push(nullptr)【標識t二次入棧】, call.push(t->left)。
                //此時t並沒有被處理(賣萌)。棧頂是t->left, 所以現在進入t->left的遞歸中。

    //res.push_back(t->val)
    t.賣萌();   //t->left 處理完了,t->left被徹底彈出棧。
                //此時棧頂是nullptr, 表示t是已經訪問過的。那麼我現在需要真正的處理t了(即,執行賣萌操作)。
                //賣萌結束後,t 就被徹底彈出棧了。
    

    dfs(t->right); 
}         //中序遍歷

 



 

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