Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索
Depth-first search
Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data structures.
The algorithm starts at the root node (selecting some arbitrary node as the root node in the case of a graph) and explores as far as possible along each branch before backtracking 回溯.
For the following graph:
a depth-first search starting at A,
assuming that the left edges in the shown graph are chosen before right edges,
and assuming the search remembers previously visited nodes and will not repeat them (since this is a small graph),
will visit the nodes in the following order: A, B, D, F, E, C, G.
The edges traversed in this search form a Trémaux tree, a structure with important applications in graph theory.
Performing the same search without remembering previously visited nodes results in visiting nodes in the order A, B, D, F, E, A, B, D, F, E, etc. forever, caught in the A, B, D, F, E cycle and never reaching C or G.
Iterative deepening is one technique to avoid this infinite loop and would reach all nodes.
深度优先的算法实现
Input: A graph G and a vertex v of G
Output: All vertices reachable from v labeled as discovered
A recursive implementation of DFS:[5]
1 procedure DFS(G,v):
2 label v as discovered
3 for all edges from v to w in G.adjacentEdges(v) do
4 if vertex w is not labeled as discovered then
5 recursively call DFS(G,w)
The order in which the vertices are discovered by this algorithm is called the lexicographic order.
A non-recursive implementation of DFS with worst-case space complexity O(|E|):[6] (使用栈,先进后出)
1 procedure DFS-iterative(G,v):
2 let S be a stack
3 S.push(v)
4 while S is not empty
5 v = S.pop()
6 if v is not labeled as discovered:
7 label v as discovered
8 for all edges from v to w in G.adjacentEdges(v) do
9 S.push(w)
These two variations of DFS visit the neighbors of each vertex in the opposite order from each other: the first neighbor of v visited by the recursive variation is the first one in the list of adjacent edges, while in the iterative variation the first visited neighbor is the last one in the list of adjacent edges. The recursive implementation will visit the nodes from the example graph in the following order: A, B, D, F, E, C, G. The non-recursive implementation will visit the nodes as: A, E, F, B, D, C, G.
The non-recursive implementation is similar to breadth-first search but differs from it in two ways:
- it uses a stack instead of a queue, and
- it delays checking whether a vertex has been discovered until the vertex is popped from the stack rather than making this check before adding the vertex.
Breadth-first search
Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph data structures.
It starts at the tree root (or some arbitrary node of a graph, sometimes referred to as a 'search key'[1]), and explores all of the neighbor nodes at the present depth prior to moving on to the nodes at the next depth level.
It uses the opposite strategy as depth-first search, which instead explores the highest-depth nodes first before being forced to backtrack回溯 and expand shallower nodes.
shallower是shallow的比较级,较浅的
广度优先的实现 (使用队列,先进先出)
Input: A graph Graph and a starting vertex顶点 root of Graph
Output: Goal state. The parent links trace the shortest path back to root
1 procedure BFS(G,start_v):
2 let S be a queue
3 S.enqueue(start_v)
4 while S is not empty
5 v = S.dequeue()
6 if v is the goal:
7 return v
8 for all edges from v to w in G.adjacentEdges(v) do
9 if w is not labeled as discovered:
10 label w as discovered
11 w.parent = v
12 S.enqueue(w)
More details
This non-recursive implementation is similar to the non-recursive implementation of depth-first search, but differs from it in two ways:
- it uses a queue (First In First Out) instead of a stack and
- it checks whether a vertex顶点 has been discovered before enqueueing the vertex rather than delaying this check until the vertex is dequeued from the queue.
The Q queue contains the frontier along which the algorithm is currently searching.
Nodes can be labelled as discovered by storing them in a set, or by an attribute on each node, depending on the implementation.
Note that the word node is usually interchangeable with the word vertex.
The parent attribute of each vertex is useful for accessing the nodes in a shortest path, for example by backtracking from the destination node up to the starting node, once the BFS has been run, and the predecessors nodes have been set.
Breadth-first search produces a so-called breadth first tree. You can see how a breadth first tree looks in the following example.
Depth-first search and Breadth-first search 深度优先搜索和广度优先搜索的更多相关文章
- DFS_BFS(深度优先搜索 和 广度优先搜索)
package com.rao.graph; import java.util.LinkedList; /** * @author Srao * @className BFS_DFS * @date ...
- 【Python排序搜索基本算法】之深度优先搜索、广度优先搜索、拓扑排序、强联通&Kosaraju算法
Graph Search and Connectivity Generic Graph Search Goals 1. find everything findable 2. don't explor ...
- 【js数据结构】图的深度优先搜索与广度优先搜索
图类的构建 function Graph(v) {this.vertices = v;this.edges = 0;this.adj = []; for (var i = 0; i < this ...
- DFS或BFS(深度优先搜索或广度优先搜索遍历无向图)-04-无向图-岛屿数量
给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1: 输入: ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析(新手向)
深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每个点仅被访问一次,这个过程就是图的遍历.图的遍历常用的有深度优先搜索和广度优先搜索,这两者对于有向图和无向图 ...
- 深度优先搜索(DFS)和广度优先搜索(BFS)
深度优先搜索(DFS) 广度优先搜索(BFS) 1.介绍 广度优先搜索(BFS)是图的另一种遍历方式,与DFS相对,是以广度优先进行搜索.简言之就是先访问图的顶点,然后广度优先访问其邻接点,然后再依次 ...
- 深度优先搜索DFS和广度优先搜索BFS简单解析
转自:https://www.cnblogs.com/FZfangzheng/p/8529132.html 深度优先搜索DFS和广度优先搜索BFS简单解析 与树的遍历类似,图的遍历要求从某一点出发,每 ...
- Unity中通过深度优先算法和广度优先算法打印游戏物体名
前言:又是一个月没写博客了,每次下班都懒得写,觉得浪费时间.... 深度优先搜索和广度优先搜索的定义,网络上已经说的很清楚了,我也是看了网上的才懂的,所以就不在这里赘述了.今天讲解的实例,主要是通过自 ...
- 广度优先搜索(Breadth First Search, BFS)
广度优先搜索(Breadth First Search, BFS) BFS算法实现的一般思路为: // BFS void BFS(int s){ queue<int> q; // 定义一个 ...
随机推荐
- 强化学习--Actor-Critic---tensorflow实现
完整代码:https://github.com/zle1992/Reinforcement_Learning_Game Policy Gradient 可以直接预测出动作,也可以预测连续动作,但是无 ...
- Linux 中常用的命令
Linux中的常用命令: 终端快捷键: Ctrl + a/Home 切换到命令行开始 Ctrl + e/End 切换到命令行末尾 Ctrl + l 清除屏幕内容,效果等同于clear Ctrl + u ...
- BufferReader BufferWriter
Copying information from one file to another with 'BufferReader BufferWriter' public class Demo5 { p ...
- 使用Oozie中workflow的定时任务重跑hive数仓表的历史分期调度
在数仓和BI系统的开发和使用过程中会经常出现需要重跑数仓中某些或一段时间内的分区数据,原因可能是:1.数据统计和计算逻辑/口径调整,2.发现之前的埋点数据收集出现错误或者埋点出现错误,3.业务数据库出 ...
- mac电脑复制粘贴使用command+c command+v
mac电脑复制粘贴使用command+c command+v系统偏好设置--键盘--修饰键(右下角),将ctrl键和command键的功能对换一下即可用ctrl+c ctrl+v复制粘贴缺点:所有的c ...
- Oracle中字符串连接的实现方法
1.和其他数据库系统类似,Oracle字符串连接使用“||”进行字符串拼接,其使用方式和MSSQLServer中的加号“+”一样. 例如: SELECT '工号为'||FNumber||'的员工姓名为 ...
- tomcat 启动时遇到org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet contained no TLDs
当发生这样的错误的时候 org.apache.jasper.servlet.TldScanner.scanJars At least one JAR was scanned for TLDs yet ...
- mysql误删数据快速恢复
相信后端研发的同学在开发过程经常会遇到产品临时修改线上数据的需求,如果手法很稳那么很庆幸可以很快完成任务,很不幸某一天突然手一抖把表里的数据修改错误或者误删了,这个时候你会发现各种问题反馈接踵而来.如 ...
- Golang切片的三种简单使用方式及区别
概念 切片(slice)是建立在数组之上的更方便,更灵活,更强大的数据结构.切片并不存储任何元素而只是对现有数组的引用. 三种方式及细节案例 ①定义一个切片,然后让切片去引用一个已经创建好的数组 pa ...
- log4j升级到logback
虽然现在log4j已经基本上不更新很久了,但实际上升级log4j到logback最大的难度并不在于本身的替换,而是现有大量的三方jar依然使用log4j,以至于无法100%的exclude掉,所以很有 ...