通用的樹的前中後序非遞歸遍歷方法(Leetcode 144 145 146)

樹的前中後序遍歷定義:

前:中左右
中:左中右
後:左右中
遞歸版本非常好寫,這裏不再贅述,僅考慮非遞歸使用棧進行遍歷
首先來看節點結構

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

以前學的版本

中序

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

前序

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ret;
        stack<TreeNode*> stk;
        while (!stk.empty() || root != NULL) {
            if (root != NULL) {
                ret.push_back(root->val);
                stk.push(root);
                root = root->left;
            }
            else {
                root = stk.top();
                stk.pop();
                root = root->right;
            }
        }
        return ret;
    }
};

這兩種前中序的非遞歸遍歷寫法也是主流的寫法,差別也僅有ret.push_back(root->val);訪問節點這一句話的位置不同,但這種寫法是沒有辦法寫樹的後序遍歷的。

船新的版本

其核心就是在棧中使用了pair二元組來標記這是第幾次被訪問,其實就是完完全全地模擬了遞歸的寫法。
後序:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ret;
        stack<pair<TreeNode*, int>> stk;
        if (root)
            stk.push({root, 0});
        while (!stk.empty()) {
            pair<TreeNode*, int> cur = stk.top();
            if (cur.second == 0) { // 第零次被訪問
                stk.top().second = 1; // 標記爲1
                if (cur.first->left) 
                    stk.push({cur.first->left, 0});
            }
            else if (cur.second == 1) {  // 第一次被訪問
                stk.top().second = 2;	// 標記位2
                if (cur.first->right)
                    stk.push({cur.first->right, 0}); 
            }
            else if (cur.second == 2) {  // 第二次被訪問
                ret.push_back(cur.first->val);
                stk.pop();
            }
        }
        return ret;
    }
};

中序:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        stack<pair<TreeNode*, int>> stk;
        if (root)
            stk.push({root, 0});
        while (!stk.empty()) {
            pair<TreeNode*, int> cur = stk.top();
            if (cur.second == 0) {
                stk.top().second = 1;
                if (cur.first->left) 
                    stk.push({cur.first->left, 0});
            }
            else if (cur.second == 1) {
                stk.top().second = 2;
                ret.push_back(cur.first->val);
            }
            else if (cur.second == 2) {
                stk.pop();
                if (cur.first->right)
                    stk.push({cur.first->right, 0});
            }
        }
        return ret;
    }
};

前序

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ret;
        stack<pair<TreeNode*, int>> stk;
        if (root)
            stk.push({root, 0});
        while (!stk.empty()) {
            pair<TreeNode*, int> cur = stk.top();
            if (cur.second == 0) {
                stk.top().second = 1;
                ret.push_back(cur.first->val);
            }
            else if (cur.second == 1) {
                stk.top().second = 2;
                if (cur.first->left) 
                    stk.push({cur.first->left, 0});
            }
            else if (cur.second == 2) {
                stk.pop();
                if (cur.first->right)
                    stk.push({cur.first->right, 0});
            }
        }
        return ret;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章