树的非递归遍历

树的非递归遍历

1. 中根遍历

思路:
一直遍历左子树 p = p->left;
直到p为空。此时訪问栈顶元素,栈顶元素出栈。開始遍历右子树p = p->right;
遍历右子树的左子树

出栈时訪问

/**
 1. Definition for a binary tree node.
 2. struct TreeNode {
 3.     int val;
 4.     TreeNode *left;
 5.     TreeNode *right;
 6.     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 7. };
*/
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ret;
        if(root == NULL){
            return ret;
        }        
        stack<TreeNode*> ss;
        TreeNode* p = root;
        while(ss.empty()==false || p!=NULL){
            if(p != NULL){
                ss.push(p);
                p = p->left;
            }
            else{
                p = ss.top();
                ss.pop();
                ret.push_back(p->val);
                p = p->right;
            }

        }
        return ret;
    }

};

2. 先根遍历

与中根思路一样。仅仅是在入栈即訪问该节点

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

还有一种思路:
先把根压入栈,出栈时才訪问。
依照右左顺序把两个孩子压栈

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

比較推荐另外一种,仅仅是第一种与树的中根遍历基本同样除了訪问位置。便于记忆。

3. 后根遍历

採用上述中根和先根统一的思路。前两者都须要訪问完左子树(左回),即能够pop当前节点。再訪问右子树
不同于上述两者,后根须要訪问完右子树才干pop当前节点(右回),因此新定义了一个标记,開始訪问右子树时标记该节点。
当p为空,且栈顶元素被标记才訪问栈顶元素。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ret;
        if(root == NULL){
            return ret;
        }
        stack<TreeNode *> ss;
        unordered_map<TreeNode *,bool> mymap;  //here
        TreeNode *p = root;
        while(ss.empty()==false || p!=NULL){
            if(p != NULL){
                ss.push(p);
                mymap[p] = false;//here
                p = p->left;
            }
            else{
                if(mymap[ss.top()] == false){
                    p = ss.top()->right;
                    mymap[ss.top()] = true;
                }
                else{
                    //visit ss.top();
                    ret.push_back(ss.top()->val);
                    ss.pop();
                }
            }
        }

        return ret;
    }
};
posted @ 2017-07-30 08:10  brucemengbm  阅读(257)  评论(0编辑  收藏  举报