二叉树的前,中,后,层序遍历

前序遍历

给定一个二叉树,返回它的 前序 遍历。
示例:
在这里插入图片描述

二叉树的遍历通常有两种方法,分别为递归法和迭代法,首先介绍递归法,该方法是实现最简单的,首先需要知道前序遍历的特点,先存储树的根节点然后遍历左子树并对左子树进行相应的操作,最后遍历右子树并对右子树进行相应的操作,采用深度优先搜索向下遍历,这里需要定义一个递归函数来遍历该树。
递归法

vector<int> preorderTraversal(TreeNode* root) {
        vector<int>res;
        helper(root,res);      //定义一个辅助函数进行遍历
        return res;
    }
void helper(TreeNode *root,vector<int>&res){
        if(root!=nullptr){
            res.push_back(root->val);         //首先将根节点存入到结果中
            helper(root->left,res);			//遍历左子树,并对左子树进行相应的操作
            helper(root->right,res);		//遍历右子树,并对右子树进行相应的操作
        }
    }

接下来介绍迭代法,每个递归法都可以转化为相应的迭代法,迭代法需要一个辅助栈来存储树的子节点,其进出栈过程如下
在这里插入图片描述
迭代法代码实现如下:

vector<int>preorderTraversal(TreeNode* root){
        stack<TreeNode*>st;
        vector<int>res;
        if(root==nullptr)return res;
        st.push(root);								//首先将根节点入栈
        while(!st.empty()){
            TreeNode *first=st.top();				//将栈顶出栈
            st.pop();
            res.push_back(first->val);				//将出栈元素加入到结果中
            if(first->right!=nullptr){				//将栈顶的右子节点入栈
                st.push(first->right);
            }
            if(first->left!=nullptr){				//将栈顶的左子节点入栈
                st.push(first->left);
            }
        }
        return res;
    }

中序遍历

给定一个二叉树,返回它的中序 遍历。
在这里插入图片描述

同样中序遍历也有两种方法来实现,分别为递归法和迭代法,其中递归法的实现和前序遍历几乎一样,只是改变了存储时的顺序,中序遍历顺序为:先存储左子节点的值之后遍历根节点并对根节点进行同样的操作,左后遍历右节点并进行同样的操作。采用深度优先搜索自上而下进行遍历,需要一个辅助函数进行遍历。
递归代码如下:

vector<int> inorderTraversal(TreeNode* root) {
        vector<int>ans;
        if(root)
            helper(root,ans);
        return ans;
    }
    void helper(TreeNode *root,vector<int>&ans){
        if(root->left!=nullptr)
            helper(root->left,ans);
        ans.push_back(root->val);
        if(root->right!=nullptr)
            helper(root->right,ans);
    }

可看出中序遍历和前序遍历代码完全一样,只是存储时的顺序不一样。

接下来介绍递归法实现中序遍历,同样需要一个辅助栈来存储遍历的过程,这里同样提供一张图来讲解

在这里插入图片描述
迭代代码实现如下:

vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*>helper;
        vector<int>res;
        TreeNode *curr=root;
        while(curr!=nullptr || !helper.empty()){
            while(curr!=nullptr){					//一直遍历左子节点直到叶子节点,并将其入栈
                helper.push(curr);
                curr=curr->left;
            }
            curr=helper.top();						//栈顶出栈,并将其值存储到结果中
            helper.pop();
            res.push_back(curr->val);				
            curr=curr->right;						//对右子节点进行同样的操作
        }
        return res;
    }

后序遍历

给定一个二叉树,返回它的 后序 遍历。
在这里插入图片描述

二叉树的后续遍历采用递归实现时和前序中序代码类似,只是改变了存储顺序,后序遍历的顺序为:先遍历左节点,后遍历右节点,最后存储根节点,代码实现也十分简单。
递归法代码

    vector<int> postorderTraversal(TreeNode* root) {
        vector<int>res;
        helper(root,res);
        return res;
    }
    void helper(TreeNode*root,vector<int>&res){
        if(root!=nullptr){
            helper(root->left,res);					//改变遍历顺序,先左节点,后右节点最后存储根节点数据。
            helper(root->right,res);
            res.push_back(root->val);
        }
    }

后序遍历的迭代实现有些复杂这里有一个巧妙的方法,即同中序遍历代码类似,只是先遍历所有的右子节点,再根节点,最后左子节点,在最后输出时将存储的数据倒序输出。这里仍然以图的方式给出。

在这里插入图片描述
迭代代码如下

vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*>helper;
        vector<int>res;
        if(root==nullptr)return res;
        helper.push(root);
        while(!helper.empty()){
            TreeNode *first=helper.top();
            helper.pop();
            res.push_back(first->val);
            if(first->left!=nullptr){
                helper.push(first->left);
            }
            if(first->right!=nullptr){
                helper.push(first->right);
            }
        }
        reverse(res.begin(),res.end());
        return res;
    }

层序遍历

给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
例如:
给定二叉树: [3,9,20,null,null,15,7],
在这里插入图片描述

层序遍历同样有两种实现方式,不过其递归方式和前几种不一样,层序是广度优先搜索实现的,即需要先将某一层的遍历完再进入下一层,因此需要一个记录层数的变量level,设res代表结果列表,列表的长度代表树的层数,当列表长度和层数level相等时需要添加一个空列表,并将当前节点添加到列表res[level]中,对于非空左右子节点同样如此操作,即helper(node->left或node->right,level+1)
代码如下

vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>>res;
        helper(root,0,res);
        return res;
    }
    void helper(TreeNode *root,int level,vector<vector<int>>&res){
        if(root!=nullptr){
            if(res.size()==level)					//当列表长度和层数相等时,添加一个空列表
                res.push_back(vector<int>{});
            res[level].push_back(root->val);		//将当前节点的值存入到结果数组中
            helper(root->left,level+1,res);			//对左右子节点进行同样的操作
            helper(root->right,level+1,res);
        }
    }

接下来将使用迭代法实现层序遍历,不同的是这里需要使用辅助队列记录每层的节点,使用level来记录树的层数,遍历每一层时将每层的节点全部存入到队列中,再通过遍历队列将节点值存入到结果数组中。
中序遍历代码如下

vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*>helper;
        vector<vector<int>>res;
        if(root==nullptr)return res;
        helper.push(root);
        int level=0;
        while(!helper.empty()){
            res.push_back(vector<int>{});				//每层添加一个空列表
            int len_queue=helper.size();				//计算队列的长度
            for(int i=0;i<len_queue;i++){				//遍历队列,同时将每个节点的非空子节点存入到队列中
                TreeNode* first=helper.front();
                helper.pop();
                res[level].push_back(first->val);
                if(first->left!=nullptr){
                    helper.push(first->left);
                }
                if(first->right!=nullptr){
                    helper.push(first->right);
                }
            }
            level++;
        }
        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值