【二叉树】二叉树的深度优先遍历DFS(前中后序遍历)和广度优先遍历BFS(层序遍历)详解【力扣144,94,145,102】【超详细的保姆级别教学】

【二叉树】二叉树的深度优先遍历(前中后序遍历)和广度优先遍历(层序遍历)详解【超详细的保姆级别教学】

先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力 看完之后别忘记关注我哦!️️️

这篇博客包含了我们出血二叉树时最先学的,也是最基础的知识点:二叉树的遍历。
本篇建议收藏后食用~

博主这里提供题目的传送门:学完的伙伴可以顺便去力扣把题给做了。但是我们要注意的是,学会这些遍历方法才是重点,而不是单纯地把题目做完。

OJ144:二叉树的前序遍历
OJ94:二叉树的中序遍历
OJ145:二叉树的后序遍历
OJ102:二叉树的层序遍历

树的结构

//取自leetcode
/**
 * 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) {}
 * };
 */

深度优先遍历(DFS)

什么是深度优先遍历

深度优先遍历:
指的是,遍历的时候,向二叉树的深度先遍历,一般采用的方式是递归,即遇到二叉树底层才回溯。
而深度优先遍历包括:前序,中序和后序遍历。
如:前序遍历:
如图:在这颗二叉树中:
在这里插入图片描述
我们在深度优先遍历中,往深度先遍历。因此以前序遍历为例来说,遍历顺序就是A-B-D-E-C,我们是先往下走,至于具体怎么遍历,我在下面会详细讲。
广度优先遍历:
层序遍历就是一种广度优先遍历,这种方法在遍历二叉树的时候,是一层一层来的,也就是,往宽的方向走。如上图例子:遍历顺序就是A-B-C-D-E。

关于DFS深度优先遍历,我们可以使用递归法和非递归法,这里展示的是递归法,以后博主可能还会补充非递归法的过程。伙伴们持续关注哦~

前序遍历

核心:
遍历顺序:根-左子树-右子树
注意:此处不是根-左子结点-右子结点,而是根-左子树-右子树。
如图:让博主带着大家详细地介绍这个前序遍历,明白了这个前序,中序和后序都是相类似的。
在这里插入图片描述
在这幅图中:我们按照根-左-右的顺序来,遇到空就回溯,在这里,如果对函数递归不熟练的伙伴,建议先将函数递归弄明白,再继续食用。
首先我们从根开始,也就是1,1的左是否为空,不为空。所以1的左子树,也就是2为根左边那棵树,所以我们找到2
此时的顺序是1-2
2的左边为空吗?不为空,所以找到4,此时为1-2-4
4的左边为空吗?为空,所以回溯,回到4,此时为1-2-4-null
回到4后,看4的右边,为空吗?不为,所以1-2-4-null-8
8的左为空吗,为空。右为空吗,为空。此时为1-2-4-null-8-null-null。
两边都为空,我们要回溯,4的左右我们都看了,所以回到2
2的右边为空吗?不为,找到5,所以此时1-2-4-null-8-null-null-5.

看到这里我们应该可以继续推出后面的遍历顺序了
最后的结果是:
1-2-4-null-8-null-null-5-null-null-3-6-9-null-null-10-null-null-7-null-null
大家可以对一下答案,看看自己算对没有哦。

知道思路,我们可以写代码了:

class Solution {
public:
	//前序遍历
	void preordertraversal(TreeNode* cur, vector<int>& vec) {
		//确定终止条件
		if (cur == NULL) {
			return;
		}
		//确定单层递归的逻辑
		vec.push_back(cur->val);
		preordertraversal(cur->left, vec);
		preordertraversal(cur->right, vec);
	}
};

中序遍历和后序遍历

中序遍历和后序遍历其实和前序遍历大部分是一样的。
中序遍历顺序:左子树-根-右子树
后序遍历顺序:左子树-右子树-根

关于具体怎么遍历,和前序的思路其实是一样的,只是顺序换一下,这里就不赘述了。
看代码我们可以发现,其实就是取节点和两个递归函数之间的顺序变了而已,其它都是一样的。

中序遍历:

//中序遍历
class Solution {
public:
    void inOrder(TreeNode* root, vector<int>& res) {
        if (!root) {
            return;
        }
        //就是下面三者顺序调整一下而已
        inOrder(root->left, res);
        res.push_back(root->val);//放中间
        inOrder(root->right, res);
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        inorder(root, res);
        return res;
    }
};

后序遍历:

//后序遍历:
class Solution {
public:
    void postOrder(TreeNode*root,vector<int>&ret){
        if(root==NULL)return;
        postOrder(root->left,ret);
        postOrder(root->right,ret);
        ret.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int>ret;
        postOrder(root,ret);
        return ret;
    }
};

整个深度优先遍历,其实就是递归遍历:在这里插入图片描述

广度优先遍历(BFS)

非递归遍历
二叉树的层序遍历需要用到队列的知识,暂时没学过队列的伙伴可以通过传送门先学习队列,再继续食用本篇~【栈和队列】纯C实现栈和队列以及其基本操作-宝藏级别数据结构教程【保姆级别详细教学】

层序遍历的思路比较简单,但实现过程稍微难一点
思路:即一层一层访问:
在这里插入图片描述
如何实现呢?
我们要通过队列来帮助我们实现
过程为:
图片取自百度:

借助队列的先进先出
核心思路是:上一层带下一层

访问到数据的时候,push()进队列里面,然后在访问下一层的同时将上一层的pop()出去一个值。最后当队列为空的时候,我们结束遍历。按照动图所示,我们就可以完成一层一层的遍历了。具体如动图所示。

层序遍历:

//结果插入vector中
class Solution {
private:
    vector<vector<int>>ret;
public:
    vector<vector<int>> levelOrder(BTNode* root) {
        if (!root) {
            return ret;
        }
        queue<BTNode*>q;//队列存地址
        q.push(root);
        while (!q.empty()) {//队列为空,结束遍历
            int curentLevalSize = q.size();
            ret.push_back(vector <int>());//这里指的是二维数组的行地址
            for (int i = 0; i < curentLevalSize; i++) {
                BTNode* node = q.front();//先保存队头元素,否则弹走了就找不到了
                q.pop();//每次都要弹出一个元素
                ret.back().push_back(node->data);//将数据push进结果数组里
                //如果左边不为空,把左边push进队列
                if (node->left) {
                    q.push(node->left);
                }
                //如果右边不为空,把右边push进队列
                if (node->right) {
                    q.push(node->right);
                }
            }
        }
        return ret;
    }
};

尾声

相信大家看到这里,已经对二叉树的DFS,BFS遍历有了一定的认识和了解了。这些都是我们学习数据结构最最基础的东西,也是必不可少的知识,我们必须掌握。如果你感觉这篇文章对你有帮助的话,不要忘了点赞关注和收藏哦!

posted @ 2022-02-27 01:55  背包Yu  阅读(14)  评论(0编辑  收藏  举报  来源