二叉树前序中序后序遍历的递归实现以及迭代实现

二叉树的简单介绍

二叉树前序中序后序遍历的递归实现以及迭代实现_第1张图片
就是每个节点最多有两个子节点

遍历方式

根据访问根节点的不同顺序随之而来也有三种访问方式

  • 先序遍历 : 先访问根节点再访问左子叶和右子叶
  • 中序遍历:先访问左子叶再访问根节点和右子叶
  • 后序遍历:先访问左子叶和右子叶再访问根节点

通过观察二叉树的结构,根节点下又是两颗二叉树,所以我们想要遍历二叉树可以采用递归的方式进行遍历
递归是不断的遍历,将每一次的参数压入栈中,直到底部,开始出栈返回
因此我们也可以通过迭代的方式对其进行遍历,下面来介绍这几种方式

递归遍历

二叉树的递归很简单,主要这三个步骤

  1. 确定函数的返回值和参数
  2. 确定终止条件
  3. 确定单层的逻辑

递归法

先序遍历

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

中序遍历

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

后序遍历

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

迭代法

先序遍历

首先我们来想一下在大脑里是怎么完成先序遍历的,先找根节点的左子树然后一路找到底开始返回,这个和栈很像,只不过我们在访问左子树的时候已经默认把右子树放在了后面去访问。因此我们要用栈去实现的时候应该右子树先进栈保存,而二叉树有很多子树,因此可以都当作一样的来处理

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        //空指针直接返回
        if(root==nullptr)
        {
            return res;
        }
        // 头节点先进栈
        st.push(root);
        while(!st.empty())
        {	// 获取栈顶元素
            TreeNode *node = st.top();
            // 进数组
            res.push_back(node->val);
            // 出栈
            st.pop();
            if(node->right!=nullptr)
            {	// 右子树先进栈
                st.push(node->right);
            }
            if(node->left!=nullptr)
            {	// 左子树进栈
                st.push(node->left);
            }
        }
        return res;
    }
};

中序遍历

还是一样我们怎么手动模拟中序遍历的,直接找到最左节点然后开始朝上进行回访,再回访的过程中同时要查看右子树

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

后序遍历

后续遍历更加简单,和先序相比就是根节点访问顺序不一样,更改一下即可

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

你可能感兴趣的:(算法,java,leetcode)