目录:
- 概述
- 以二叉树为例,实现BFS和DFS遍历
- 与深度优先算法和广度优先算法相关的习题整理(参见下一篇博客)
第一部分:关于深度优先算法和广度优先算法的概述
以二叉树为例,介绍BFS和DFS遍历的过程
BFS:广度优先算法(类似于水的涟漪)
对于广度优先遍历二叉树,也就是按层次的去遍历。依次遍历根节点,然后是左孩子和右孩子。所以要遍历完当前节点的所有孩子,这样才是层次遍历嘛。此时我们就不能用栈这个数据结构了,因为栈只能在栈顶操作。在这里,我们需要根据左右孩子的顺序来输出,所以就是先进先出的原则,那么我们当然就想到了队列这个数据结构。可以在rear依次插入左右孩子,在front依次读取并删除左右孩子,这样就保证了层次的输出。
广度优先遍历:广度优先遍历是连通图的一种遍历策略,因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域故得名。
根据广度优先遍历的特点我们利用Java数据结构队列Queue来实现。
广度优先搜索的步骤为:
(1)、节点1进队,节点1出队,访问节点1
(2)、节点1的孩子节点2进队,节点3进队。
(3)、节点2出队,访问节点2,节点2的孩子节点4进队,节点5进队;
(4)、节点3出队,访问节点3,节点3的孩子节点6进队,节点7进队;
(5)、节点4出队,访问节点4,节点4没有孩子节点。
(6)、节点5出队,访问节点5,节点5没有孩子节点。
(7)、节点6出队,访问节点6,节点6没有孩子节点。
(8)、节点7出队,访问节点7,节点7没有孩子节点,结束。
习题:力扣102. 二叉树的层次遍历
给定一个二叉树,返回其按层次遍历的节点值。 (即逐层地,从左到右访问所有节点)。
例如:
给定二叉树: [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其层次遍历结果:
[
[3],
[9,20],
[15,7]
]
解题思路:BFS
代码实现:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> list=new ArrayList<>();
if(root==null) {
return list;
}
Deque<TreeNode> deq=new LinkedList<TreeNode>();
deq.add(root);
while(!deq.isEmpty()) {
//每一层的节点值
List<Integer> al=new ArrayList<>();
int size=deq.size();
for(int i=0;i<size;i++) {
TreeNode node=deq.poll();
al.add(node.val);
if(node.left!=null) {
deq.add(node.left);
}
if(node.right!=null) {
deq.add(node.right);
}
}
list.add(al);
}
return list;
}
}
DFS:深度优先算法(类似于“一根筋”)
深度优先遍历,也就深入的遍历,沿着每一个分支直到走到最后,然后才返回来遍历剩余的节点。二叉树不同于图,图需要标记节点是否已经访问过,因为可能会存在环,而二叉树不会出现环,所以不需要标记。那么,我们只需要一个栈空间,来压栈就好了。因为深度优先遍历,遍历了根节点后,就开始遍历左子树,所以右子树肯定最后遍历。我们利用栈的性质,先将右子树压栈,然后在对左子树压栈。此时,左子树节点是在top上的,所以可以先去遍历左子树。
深度优先遍历:深度优先遍历是图论中的经典算法。其利用了深度优先搜索算法可以产生目标图的相应拓扑排序表,采用拓扑排序表可以解决很多相关的图论问题,如最大路径问题等等。
根据深度优先遍历的特点我们利用Java集合类的栈Stack先进后出的特点来实现。我用二叉树来进行深度优先搜索。
深度优先搜索的步骤为:
(1)、首先节点 1 进栈,节点1在栈顶;
(2)、然后节点1出栈,访问节点1,节点1的孩子节点3进栈,节点2进栈;
(3)、节点2在栈顶,然后节点2出栈,访问节点2
(4)、节点2的孩子节点5进栈,节点4进栈
(5)、节点4在栈顶,节点4出栈,访问节点4,
(6)、节点4左右孩子为空,然后节点5在栈顶,节点5出栈,访问节点5;
(7)、节点5左右孩子为空,然后节点3在站顶,节点3出栈,访问节点3;
(8)、节点3的孩子节点7进栈,节点6进栈
(9)、节点6在栈顶,节点6出栈,访问节点6;
(10)、节点6的孩子为空,这个时候节点7在栈顶,节点7出栈,访问节点7
(11)、节点7的左右孩子为空,此时栈为空,遍历结束。
习题:力扣257. 二叉树的所有路径
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
输入:
1
/ \
2 3
\
5
输出: [“1->2->5”, “1->3”]
解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3
解题思路:DFS
实现代码:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
List<String> res=new ArrayList<>();
String path="";
//代码的鲁棒性判断
if(root==null) {
return res;
}
dfs_bin(path,root,res);
return res;
}
private void dfs_bin(String path, TreeNode root, List<String> res) {
if(root==null) {
return;
}
if(root.left==null && root.right==null) {
path+=root.val;
res.add(path);
return;
}else {
dfs_bin(path+root.val+"->",root.left,res);
dfs_bin(path+root.val+"->",root.right,res);
}
}
}
参考:
(1) https://blog.csdn.net/kuailekemi/article/details/9234269
(2)https://blog.csdn.net/weixin_42289193/article/details/81741756