1. 程式人生 > >LeetCode 145 ——二叉樹的後序遍歷

LeetCode 145 ——二叉樹的後序遍歷

1. 題目

2. 解答

2.1. 遞迴法

定義一個存放樹中資料的向量 data,從根節點開始,如果節點不為空,那麼

    1. 遞迴得到其左子樹的資料向量 temp,將 temp 合併到 data 中去
    1. 遞迴得到其右子樹的資料向量 temp,將 temp 合併到 data 中去
    1. 將當前節點的數值加入到 data 中
/**
 * 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> preorderTraversal(TreeNode* root) {
        
        vector<int> data = {};
        vector<int> temp = {};

        if (root != NULL)
        {
            temp = postorderTraversal(root->left);
            data.insert(data.end(),temp.begin(),temp.end());
            temp = postorderTraversal(root->right);
            data.insert(data.end(),temp.begin(),temp.end());
            data.push_back(root->val);
        }
        
        return data;        
    }
};
2.2. 迭代法一

仿照前序遍歷的思想,只不過這次我們的順序為中-右-左,然後倒序將其加入到向量中,即為後序左-右-中的結果。

定義一個存放樹中節點的棧 node_stack 和存放資料的向量 data,從根節點開始,如果節點不為空或者棧非空,迴圈以下過程:

    1. 如果節點非空,將節點的值加入 data 的頭部,如果節點有左孩子,將節點左孩子壓入棧,節點指向其右孩子,迴圈直到節點為空
    1. 如果節點為空,棧非空,則彈出棧頂節點
/**
 * 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> preorderTraversal(TreeNode* root) {

        // 按照中右左前序遍歷,倒序儲存即為左右中
        vector<int> data = {};
        stack<TreeNode*> node_stack;
        TreeNode* temp = root;
        
        while (temp || !node_stack.empty())
        {
            while(temp != NULL)
            {
                data.insert(data.begin(), temp->val); // 在頭部插入
                if (temp->left)    node_stack.push(temp->left);
                temp = temp->right;
            }
            
            // 若最後一個節點沒有左子節點,棧為空
            if (!node_stack.empty()) // 棧非空
            {
                temp = node_stack.top();
                node_stack.pop();
            }
        }
        
        return data;
    }
};
2.3. 迭代法二

後序遍歷的話只有某一節點的左右子節點都被訪問過之後才能訪問該節點。

定義一個存放樹中節點的棧 node_stack 和存放資料的向量 data,如果樹非空,先將根節點壓入棧。

cur 指向當前節點,pre 指向上一次訪問的節點,初始化為空,然後棧非空則迴圈以下過程:

當前節點為棧頂節點

    1. 如果節點左右子節點都為空或者上一次訪問的節點為其左右子節點中的一個,(某些節點可能只有一個子節點,所以 pre 不能為空,然後若只有左子節點,則上一次訪問的為其左子節點;若有左右子節點,按照壓棧順序,則上一次訪問的為其右子節點;)則彈出棧頂節點,將節點資料加入 data,將上一次訪問的節點指向當前節點
    1. 否則,如果存在左右子節點,先壓入其右子節點,再壓入其左子節點
/**
 * 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> preorderTraversal(TreeNode* root) {

       vector<int> data = {};
        stack<TreeNode*> node_stack;
        if (root)   node_stack.push(root); // 樹非空,先將根節點壓入棧
        
        TreeNode* cur = root;   // 當前節點
        TreeNode* last = NULL;  // 上一次訪問的節點
        
        while (!node_stack.empty())
        {
            cur = node_stack.top();
            
            if ((cur->left == NULL && cur->right == NULL) || 
                (last != NULL && (cur->left == last || cur->right == last)))
            {
                data.push_back(cur->val);
                node_stack.pop();
                last = cur;
            }
            else
            {
                if (cur->right) node_stack.push(cur->right);
                if (cur->left) node_stack.push(cur->left);
            }
        }
        
        return data;
    }
};

參考資料

獲取更多精彩,請關注「seniusen」!