非递归方法二叉树遍历

后序遍历非递归法

后续遍历,非递归法相对于前中序稍微复杂一点,因为它需要记录当前节点是否已经遍历过了。

三种方法:1)使用prev,记录输出的前一个节点 2)使用visible方法【直接记录当前节点是否访问过】。

3)对于这些非递归法,都可以使用颜色法【准备第二个栈,表示当前节点是否访问过,若访问过,直接输出】。

1.常规方法

左中右、左中右、左右中。

都是先对左节点做处理,因此可以先把左节点放到栈里。

然后取出一个节点,考虑处理右节点。【比较难理解】

需要注意

主要元素:栈、root

root 当前待遍历节点。 栈:取出下一个节点

如果右节点没有的话,或者无需向右遍历,那就把root置为空指针

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector postorderTraversal(TreeNode* root) {
        //左右中
        stack mem;
        vectorres;
        if(!root)
            return res;
        TreeNode* pre=nullptr;
        while(root||!mem.empty()){
            while(root){//先把root左节点加入
                mem.push(root);
                root=root->left;
            }
            root=mem.top();
            mem.pop();
            //加右节点,前提
            if(root->right==pre||root->right==nullptr){//右节点已经遍历
                res.push_back(root->val);
                pre=root;
                root=nullptr;
            }else{//右节点先处理
                mem.push(root);
                root=root->right;

            }

            //可以用visible来表示,不用visible就得用pre指针

        }
        return res;

    }
};

2.使用visible思路,而非prev指针。

总之先遍历每一个节点的左树。然后对当前情况分组处理。1.是当前节点已被访问过。直接输出。否则,先看当前节点和它的右节点。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector postorderTraversal(TreeNode* root) {
        //左右中
        stack mem;
        map a;
        vectorres;
        if(!root)
            return res;
        TreeNode* pre=nullptr;
        while(root||!mem.empty()){
            while(root){//先把root左节点加入
                mem.push(root);
                a[root]=1;
                root=root->left;
            }
        
            root=mem.top();
            mem.pop();
            if(a[root]>1||!root->right){
                res.push_back(root->val);
                root=nullptr;
            }else{
                mem.push(root);
                a[root]=2;
                root=root->right;
            }
            
        }
        return res;

    }
};

3.颜色标记法。【实际上是中右左换成左右中】

可以使用两个栈,或者使用pair对。

左右中——》重新push时是 中左右,入栈。

开始先把节点push到栈中(但是只是辅助遍历,并不输出)

然后从栈中取出节点,按照中 左 右的顺序重新push(中节点,因为取出过一次,认为已经处理过,就标记处理过,再取出时直接输出就可),没有处理过的,继续按照中左右顺序遍历。

【这里新加一个栈,存标记,也可以用pair对】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector postorderTraversal(TreeNode* root) {
        //左右中

        stack res;
        stack biaoji;
        vector rr;
        if(!root)
            return rr;
        res.push(root);
        biaoji.push(1);
        
        TreeNode* tmp;
        int tmpb;
        while(!res.empty()){
            tmp=res.top();
            tmpb=biaoji.top();
            res.pop();
            biaoji.pop();
            //cout<val<<"\t"<right){
                    res.push(tmp->right);
                    biaoji.push(1);
                }            
                if(tmp->left){
                    res.push(tmp->left);
                    biaoji.push(1);
                }                
                    
            }else{
                rr.push_back(tmp->val);

            }
        }
        return rr;

    }
};

前序遍历【中左右】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector preorderTraversal(TreeNode* root) {
        vector res;
        if(!root){
            return res;
        }//中左右
        stack tmp;
        while(root||!tmp.empty()){
            while(root){
                tmp.push(root);
                res.push_back(root->val);
                root=root->left;
            }
            root = tmp.top();
            tmp.pop();
            //看右
            if(root->right){
                root=root->right;
            }else{
                root=nullptr;
            }
            
        }
        return res;



    }
};

中序遍历【左中右】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector inorderTraversal(TreeNode* root) {
        vector res;
        if(!root){
            return res;
        }//左中右
        stack tmp;
        while(root||!tmp.empty()){
            while(root){
                tmp.push(root);
                
                root=root->left;
            }
            root = tmp.top();
            tmp.pop();
            res.push_back(root->val);
            //看右
            if(root->right){
                root=root->right;
            }else{
                root=nullptr;
            }
            
        }
        return res;
    }
};

你可能感兴趣的:(非递归方法二叉树遍历)