二叉树遍历(递归与非递归版本)

 # Definition for binary tree
 struct TreeNode {
      int val;
      TreeNode *left;
      TreeNode *right;
      TreeNode(int x) : val(x), left(NULL), right(NULL) {}
  };

1. 先序遍历

1.1 先序遍历的递归版本

根->左->右

class Solution {
public:
    vector<int> res;
    vector<int> preorderTraversal(TreeNode *root) {
        if(root)
            preorder(root);
        return res;
    }
    void preorder(TreeNode *root){
        if(!root) return;
        res.push_back(root->val);
        preorder(root->left);
        preorder(root->right);
    }
}

1.2 前序遍历非递归版本

  1. 先将根节点进栈
  2. 在栈不空时循环:
    2.1 访问栈顶元素*p节点
    2.2 栈顶元素*p出栈
    2.3 若其右孩子节点不空,将右孩子节点进栈
    2.4 若其左孩子节点不空,将左孩子节点进栈
class Solution {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        vector<int> res;
        if(!root) return res;
        stack<TreeNode *>stk;
        TreeNode *t;
        stk.push(root);
        while(!stk.empty()){
            t=stk.top();
            stk.pop();
            res.push_back(t->val);
            if(t->right)
                stk.push(t->right);
            if(t->left)
                stk.push(t->left);
        }
        return res;
    }
};

2. 后序遍历

2.1 后序遍历的递归版本

左->右->根

class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> res;
        if(!root) return res;
        postorder(root,res);
        return res;
    }
    void postorder(TreeNode *root,vector<int>  &v) {
        if(!root) return ;
        postorder(root->left,v);
        postorder(root->right,v);
        v.push_back(root->val);
    }
};

2.2 后序遍历的非递归版本

巧妙的方法:参考前序遍历

  • 前序遍历 根->左->右 改为 根->右->左 (进栈顺序交换左右孩子节点)
  • 结果再reverse即为左->右->根
  1. 先将根节点进栈
  2. 在栈不空时循环:
    2.1 访问栈顶元素*p节点
    2.2 栈顶元素*p出栈
    2.3 若其左孩子节点不空将左孩子节点进栈
    2.4 若其右孩子节点不空将右孩子节点进栈
  3. 结果翻转
class Solution {
public:
    vector<int> postorderTraversal(TreeNode *root) {
        vector<int> res;
        if(!root) return res;
        stack<TreeNode *>stk;
        stk.push(root);
        TreeNode *t;
        while(!stk.empty()){
            t=stk.top();
            stk.pop();
            res.push_back(t->val);
            if(t->left)
                stk.push(t->left);
            if(t->right)
                stk.push(t->right);
            
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

3. 中序遍历

3.1 中序遍历的递归版本

左->根->右

class Solution {
public:
    vector<int> res;
    vector<int> inorderTraversal(TreeNode *root) {
        if(!root) return res;
        inorder(root);
        return res;
    }
    void inorder(TreeNode *root){
        if(!root) return;
        inorder(root->left);
        res.push_back(root->val);
        inorder(root->right);
    }
};

3.2 中序遍历的非递归版本

采用一个栈来保存需要返回的节点指针

  1. 用指针*p指向当前要处理的节点
  2. 先扫描(并非访问)该节点的所有左节点,并将它们一一进栈
  3. 当无左节点时,出栈栈顶节点t,并访问它
  4. p指向t的右孩子,对右子树进行同样的处理

当节点*p的所有左下节点进栈后,这时的栈顶节点t要么没有左子树,要么左子树已经访问过,就可以访问这个栈顶节点t。如此重复循环,直到栈空为止。

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

猜你喜欢

转载自blog.csdn.net/weixin_38493025/article/details/88593496