首页 > 编程知识 正文

广度优先搜索算法,深度优先搜索的过程

时间:2023-05-03 19:45:03 阅读:50902 作者:4322

深度优先搜索和广度优先搜索都是图形搜索算法。

一、深度优先搜索(DFS ) ) ) ) )。

深度优先搜索元是对图和树的扫描算法,利用深度优先搜索算法可以生成目标图的对应拓扑整列表,利用拓扑整列表可以方便地解决许多相关图论问题,如最大路径问题。

堆栈数据结构通常用于帮助实现DFS算法。

DFS的主要思想是重复所有节点,从图中未访问的顶点v开始,沿着一条路一直向下,从该路结束的节点回到上一个节点,从另一个路继续到最后……。它的特点就是不撞南墙不回头,先走完一条路,再换一条路继续走。

树是使用树示例在深度优先搜索中遍历树的图的特殊示例。

1、从根节点1开始遍历。 相邻节点为2、3和4,首先遍历节点2,然后遍历2个子节点5,然后遍历5个子节点9。

2、上图结束了一条路(9是叶节点,是不能再扫描的节点) )此时,从9开始回到前面的节点5,调查下面的节点5中是否还有9以外的节点。 回到2、2也没有5以外的节点。 因为即使返回1、1也有2以外的节点3,所以从节点3开始进行深度优先的扫描。 如下所示。

3、同样从10追溯到6,6中没有10以外的子节点,进而追溯到3中有6以外的子点7,所以此时遍历7。

从4、7追溯到3、1,由于1还有节点4没有被遍历,所以通过在这个点沿4、8进行遍历,遍历完成。

完整节点的遍历顺序如下: 节点上的蓝色数字如下。

根据上述扫描过程,该扫描的结果是该树的先行扫描的结果。

实际上不管是前序遍历还是中序遍历、后序遍历,都属于深度优先遍历。

深度优先遍历如何实现呢? 有递归和非递归的两种实现方式。 以二叉树为例实现深度优先遍历。

递归实现:

公共类解决方案{私有状态类服务节点}公共间隔; 公共节点左; 公共节点权限; 公共节点(intvalue、Node left、Node right ) { this.value=value; this.left=left; this.right=right; }//递归地,publicstaticarraylistintegerdfs (节点趋势) ) arraylistintegerlist=new ArrayList ); if(treenode==null ) { return list; }list.add(treenode.value ); DFS(treenode.left; DFS(treenode.right; 返回列表; } } 非递归实现:

深度必须优先遍历每个节点并用于堆栈。 堆栈的特点是先进的后退,因此整个遍历过程:

先往栈中压入右节点,再压左节点,这样出栈就是先左节点后右节点了。

首先将a节点推入堆栈,堆栈(a );

一边弹出a节点,一边将a的子节点c和b推入堆栈中。 此时,b位于堆栈的最上面,是堆栈(b,c )

弹出b节点,同时将b的子节点e和d推入堆栈。 此时,d位于堆栈的最上面,堆栈(d、e、c )

如果弹出d节点且子节点未被按下,则e位于堆栈顶部,堆栈(e,c )。

弹出e节点,同时推入e的子节点I,堆栈(I,c );

.依次往下走,最终遍历完成。

//非递归实现,堆栈实现dfspublicstaticarraylistintegerdfswithstack (node root ) arraylistintegerlist=new ArrayList ); if (根==空) {返回列表; }堆叠堆栈=new堆栈(; //首先堆栈根节点

stack.push(root); while (!stack.isEmpty()){ Node treeNode = stack.pop(); //先往栈中压入右节点,再压左节点,这样出栈就是先左节点后右节点 if (treeNode.right != null){ stack.push(treeNode.right); } if (treeNode.left != null){ stack.push(treeNode.left); } list.add(treeNode.value); } return list; }

 二、广度优先搜索

       广度优先搜索算法,又称“宽度优先搜索”或“横向优先搜索”,简称“BFS”。

        广度优先搜索是连通图的一种遍历算法这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和广度优先搜索类似的思想。

        系统的展开并查找图中所有的节点,以找寻结果。并不考虑结果的可能位置,彻底地展开并检查图中的所有结点,直到找到结果为止。

        基本过程:从图中某顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发依次访问它们的邻接点,并使得“先被访问的顶点的邻接点先于后被访问的顶点的邻接点被访问,直至图中所有已被访问的顶点的邻接点都被访问到。如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问过的顶点作为新的起始点,重复上述过程,直至图中所有顶点都被访问到为止。

        一般用队列数据结构来辅助实现BFS算法。

以下图二叉树为例来看看如何用队列来实现广度优先遍历。

动图如下:

先往队列中插入左节点,再插右节点,这样出队就是先左节点后右节点。

广度优先的实现,使用队列存储结点对象,特点就是先进先出。

 

        首先将A节点插入队列中,队列中有元素(A);

  将A节点弹出,同时将A节点的左、右节点依次插入队列,B在队首,C在队尾,(B,C),此时得到A节点;

  继续弹出队首元素,即弹出B,并将B的左、右节点插入队列,C在队首,E在队尾(C,D,E),此时得到B节点;

  继续弹出,即弹出C,并将C节点的左、中、右节点依次插入队列,(D,E,F,G,H),此时得到C节点;

  将D弹出,此时D没有子节点,队列中元素为(E,F,G,H),得到D节点;

  。。。以此类推。

class TreeNode { int val; TreeNode left; TreeNode right; public TreeNode(int val) { this.val = val; }}public class Solution { public ArrayList<Integer> bfs(TreeNode root){ ArrayList<Integer> list = new ArrayList<>(); if (root == null){ return list; } Queue<TreeNode> queue = new LinkedList<>(); queue.offer(root); while (!queue.isEmpty()){ TreeNode node = queue.poll(); if (node.left != null){ queue.offer(node.left); } if (node.right != null){ queue.offer(node.right); } list.add(node.val); } return list; }}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。