LeetCode 144, 94, 145. Binary Tree Preorder/Inorder/Postorder Traversal

递归非常好写,这里主要记录非递归的写法。

 

Preorder

方法一:直接利用栈来写。

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

 

方法二:先左子树一路访问下去,全部访问完毕回溯并访问右边。p = s.top() 代表 p 的左子树已经全部访问完毕,p=s.top() 回到 p 结点,接着访问右子树。

除了这种 if else 写法,while(p){s.push(p); p=p->next} 然后接 p=s.top(); s.pop();   p=p->right; 也是可以的,思路更清楚。

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

 

Inorder

方法一:和Preorder方法一类似,直接做,但是需要一个计数器,第二次出栈的时候才可以输出。

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if (root==NULL) return res;
        unordered_map<TreeNode *,int> hash; //default value is 0;
        stack<TreeNode *> s({root});
        while (!s.empty()){
            TreeNode *cur=s.top(); s.pop();
            if (hash[cur]==0){
                ++hash[cur];
                s.push(cur);
                if(cur->left) s.push(cur->left);
            }else{
                res.push_back(cur->val);
                if(cur->right) s.push(cur->right);
            }
        }
        return res;
    }
};

 

方法二:和Preorder方法二相同,只是push_back到结果的时机不同:再访问完左子树以后再添加。

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

 

Postorder

方法一:同上

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (root==NULL) return res;
        unordered_map<TreeNode *,int> hash; //default value is 0;
        stack<TreeNode *> s({root});
        while (!s.empty()){
            TreeNode *cur=s.top(); s.pop();
            if (hash[cur]==0){
                ++hash[cur];
                s.push(cur);
                if(cur->left) s.push(cur->left);
            }else if (hash[cur]==1){
                ++hash[cur];
                s.push(cur);
                if(cur->right) s.push(cur->right);
            }else{
                res.push_back(cur->val);
            }
        }
        return res;
    }
};

 

方法二:后序遍历顺序是 左右根,反过来是 根右左,而 根右左 和 前序遍历很类似,因此把 根右左 做出来,答案reverse一下就好。

由于前序遍历有两种方法,因此这里也可以两种方法来写。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if (root==NULL) return res;
        stack<TreeNode *> s({root});
        while (!s.empty()){
            TreeNode *cur=s.top(); s.pop();
            res.push_back(cur->val);
            if (cur->left) s.push(cur->left);
            if (cur->right) s.push(cur->right);
        }
        reverse(res.begin(),res.end());
        return res;
    }
};
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode *> s;
        TreeNode *p=root;
        while (!s.empty() || p!=NULL){
            if (p!=NULL){
                s.push(p);
                res.push_back(p->val);
                p = p->right;
            }else{
                p = s.top(); s.pop();
                p = p->left;
            }
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

 

结点个数为n的话,时间复杂度为 O(n)。

空间复杂度如果只用栈,平均为树的高度,即 O(logn) ,最坏情况 O(n) 。

posted @ 2018-08-22 12:10  約束の空  阅读(170)  评论(0)    收藏  举报