1. 程式人生 > 實用技巧 >LC144/94/145 二叉樹前序/中序/後序遍歷 遞迴與非遞迴實現

LC144/94/145 二叉樹前序/中序/後序遍歷 遞迴與非遞迴實現

前序遍歷

遞迴寫法

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res, leftRes, rightRes;
        if(root == nullptr)
            return res;
        res.push_back(root->val);
        leftRes = preorderTraversal(root->left);
        rightRes = preorderTraversal(root->right);
        if(leftRes.size() > 0)
        {
            for(auto val : leftRes)
                res.push_back(val);
        }
        if(rightRes.size() > 0)
        {
            for(auto val : rightRes)
                res.push_back(val);
        }
        return res;
    }
};


遞迴寫法的時間複雜度,空間複雜度較為一般。

非遞迴寫法

使用非遞迴寫法時需要用到棧,這裡採用了LC題解中一種不錯的解法.
思路:帶有nullptr標記的節點直接訪問節點值,沒有標記則對節點本身新增標記並遍歷子節點,該過程用棧實現

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == nullptr)
            return res;
        stack<TreeNode*> nodes;
        nodes.push(root);
        while(nodes.size() > 0){
            TreeNode* nowNode = nodes.top();
            nodes.pop();
            if(nowNode != nullptr){
                // 右
                if(nowNode->right != nullptr)
                    nodes.push(nowNode->right);
                // 左
                if(nowNode->left != nullptr)
                    nodes.push(nowNode->left);
                // 根
                nodes.push(nowNode);
                nodes.push(nullptr);
            }  
            else{
                res.push_back(nodes.top()->val);
                nodes.pop();
            }
        } 
        return res;
    }
};

這個題解的優點在於只需要交換 //右,//左,//根三部分的順序即可實現先序/中序/後序遍歷方式,非常方便.

下圖是一個遍歷過程圖示,可以更清晰地看到遍歷過程。

中序遍歷

遞迴寫法

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res, leftRes, rightRes;
        if(root == nullptr)
            return res;
        leftRes = inorderTraversal(root->left);
        rightRes = inorderTraversal(root->right);
        if(!leftRes.empty()){
            for(auto val : leftRes)
                res.push_back(val);
        }
        res.push_back(root->val);
        if(!rightRes.empty()){
            for(auto val : rightRes)
                res.push_back(val);
        }
        return res;
    }
};

非遞迴寫法

參考前序遍歷的非遞迴寫法即可

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == nullptr)
            return res;
        stack<TreeNode*> nodes;
        nodes.push(root);
        while(!nodes.empty()){
            TreeNode* nowNode = nodes.top();
            nodes.pop();
            if(nowNode != nullptr){
                // 右
                if(nowNode->right != nullptr)
                    nodes.push(nowNode->right);
                // 根
                nodes.push(nowNode);
                nodes.push(nullptr);
                // 左
                if(nowNode->left != nullptr)
                    nodes.push(nowNode->left);
            }
            else{
                res.push_back(nodes.top()->val);
                nodes.pop();
            }
        }
        return res;
    }
};

後序遍歷

遞迴

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res, left, right;
        if(root == NULL)
            return res;
        left = postorderTraversal(root->left);
        right = postorderTraversal(root->right);
        for(auto iter = left.begin(); iter != left.end(); iter ++)
            res.push_back(*iter);
        for(auto iter = right.begin(); iter != right.end(); iter ++)
            res.push_back(*iter);
        res.push_back(root->val);
        return res;
    }
};

非遞迴

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root == nullptr)
            return res;
        stack<TreeNode*> nodes;
        nodes.push(root);
        while(!nodes.empty()){
            TreeNode* nowNode = nodes.top();
            nodes.pop();
            if(nowNode != nullptr){        
                // 根
                nodes.push(nowNode);
                nodes.push(nullptr);
                // 右
                if(nowNode->right != nullptr)
                    nodes.push(nowNode->right);
                // 左
                if(nowNode->left != nullptr)
                    nodes.push(nowNode->left);
            }
            else{
                res.push_back(nodes.top()->val);
                nodes.pop();
            }
        }
        return res;
    }
};