There are generally two methods to write DFS algorithm, one is using recursion, another one is using stack. (reference from Wiki Pedia)

Pseudocode for both methods:

A recursive implementation of DFS:

 procedure DFS(G,v):
label v as discovered
for all edges from v to w in G.adjacentEdges(v) do
if vertex w is not labeled as discovered then
recursively call DFS(G,w)

A non-recursive implementation of DFS(using stack):

   procedure DFS-iterative(G,v):
let S be a stack
S.push(v)
while S is not empty
v ← S.pop()
if v is not labeled as discovered:
label v as discovered
for all edges from v to w in G.adjacentEdges(v) do
S.push(w)

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 pushing the vertex.

Here's another good explenation: http://www.algolist.net/Algorithms/Graph/Undirected/Depth-first_search

Depth-first search, or DFS, is a way to traverse the graph. Initially it allows visiting vertices of the graph only, but there are hundreds of algorithms for graphs, which are based on DFS. Therefore, understanding the principles of depth-first search is quite important to move ahead into the graph theory. The principle of the algorithm is quite simple: to go forward (in depth) while there is such possibility, otherwise to backtrack.

Algorithm

In DFS, each vertex has three possible colors representing its state:

white: vertex is unvisited;

gray: vertex is in progress;

black: DFS has finished processing the vertex.

NB. For most algorithms boolean classification unvisited / visited is quite enough, but we show general case here.

Initially all vertices are white (unvisited). DFS starts in arbitrary vertex and runs as follows:

  1. Mark vertex u as gray (visited).
  2. For each edge (u, v), where u is white, run depth-first search for u recursively.
  3. Mark vertex u as black and backtrack to the parent.

Example. Traverse a graph shown below, using DFS. Start from a vertex with number 1.

Source graph.
Mark a vertex 1 as gray.
There is an edge (1, 4) and a vertex 4 is unvisited. Go there.
Mark the vertex 4 as gray.
There is an edge (4, 2) and vertex a 2 is unvisited. Go there.
Mark the vertex 2 as gray.
There is an edge (2, 5) and a vertex 5 is unvisited. Go there.
Mark the vertex 5 as gray.
There is an edge (5, 3) and a vertex is unvisited. Go there.
Mark the vertex 3 as gray.
There are no ways to go from the vertex 3. Mark it as black and backtrack to the vertex 5.
There is an edge (5, 4), but the vertex 4 is gray.
There are no ways to go from the vertex 5. Mark it as black and backtrack to the vertex 2.
There are no more edges, adjacent to vertex 2. Mark it as black and backtrack to the vertex 4.
There is an edge (4, 5), but the vertex 5 is black.
There are no more edges, adjacent to the vertex 4. Mark it as black and backtrack to the vertex 1.
There are no more edges, adjacent to the vertex 1. Mark it as black. DFS is over.


Complexity analysis
If a graph is disconnected, DFS won't visit all of its vertices. For details, see finding connected components algorithm.As you can see from the example, DFS doesn't go through all edges. The vertices and edges, which depth-first search has visited is a tree. This tree contains all vertices of the graph (if it is connected) and is called graph spanning tree. This tree exactly corresponds to the recursive calls of DFS.

Assume that graph is connected. Depth-first search visits every vertex in the graph and checks every edge its edge. Therefore, DFS complexity is O(V + E). As it was mentioned before, if an adjacency matrix is used for a graph representation, then all edges, adjacent to a vertex can't be found efficiently, that results in O(V2)complexity. You can find strong proof of the DFS complexity issues in [1].

Java Implementation

 public class Graph {
… enum VertexState {
White, Gray, Black
} public void DFS()
{
VertexState state[] = new VertexState[vertexCount];
for (int i = 0; i < vertexCount; i++)
state[i] = VertexState.White;
runDFS(0, state);
} public void runDFS(int u, VertexState[] state)
{
state[u] = VertexState.Gray;
for (int v = 0; v < vertexCount; v++)
if (isEdge(u, v) && state[v] == VertexState.White)
runDFS(v, state);
state[u] = VertexState.Black;
}
}

Summary: Depth-first Search(DFS)的更多相关文章

  1. [Algorithm] Write a Depth First Search Algorithm for Graphs in JavaScript

    Depth first search is a graph search algorithm that starts at one node and uses recursion to travel ...

  2. [算法&数据结构]深度优先搜索(Depth First Search)

    深度优先 搜索(DFS, Depth First Search) 从一个顶点v出发,首先将v标记为已遍历的顶点,然后选择一个邻接于v的尚未遍历的顶点u,如果u不存在,本次搜素终止.如果u存在,那么从u ...

  3. 幸运的袋子(深度优先遍历(Depth First Search,DFS))

    题目描述 一个袋子里面有n个球,每个球上面都有一个号码(拥有相同号码的球是无区别的).如果一个袋子是幸运的当且仅当所有球的号码的和大于所有球的号码的积. 例如:如果袋子里面的球的号码是{1, 1, 2 ...

  4. Non recursive Depth first search

    深度优先非递归实现算法: 1 递归算法: //初始化相关数据结构 DFS(G) ------------------------------------------------------------ ...

  5. Recursive Depth first search graph(adj matrix)

    1 深度优先遍历邻接矩阵 1 邻接矩阵初始化 2 访问数组初始化 3 深度优先遍历邻接矩阵图 算法如下: bool MGraph[128][128]; bool visit[128]; int vex ...

  6. 深度优先搜索(Depth First Search)

    Date:2019-07-01 15:31:11 通俗点理解就是不撞南墙不回头的那种,用栈来实现 算法实现 /* 题目描述: 有n件物品,每件物品的重量为w[i],价值为c[i].现在需要选出若干件物 ...

  7. 深度优先搜索 DFS(Depath First Search, DFS)

    深度优先搜索是一种枚举所有完整路径以遍历所有情况的搜索方法.(不撞南墙不回头) DFS一般用递归来实现,其伪代码思路过程一般如下: void DFS(必要的参数){    if (符和遍历到一条完整路 ...

  8. [MIT6.006] 14. Depth-First Search (DFS), Topological Sort 深度优先搜索,拓扑排序

    一.深度优先搜索 它的定义是:递归探索图,必要时要回溯,同时避免重复. 关于深度优先搜索的伪代码如下: 左边DFS-Visit(V, Adj.s)是只实现visit所有连接某个特定点(例如s)的其他点 ...

  9. 数据结构学习笔记05图 (邻接矩阵 邻接表-->BFS DFS、最短路径)

    数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边& ...

随机推荐

  1. mysql索引覆盖之innodb和myisam效率问题

    问题: create table A (    id varchar(64) primary key,    ver int,    ... ) 我的表有几个很长的字段varchar(3000) 在i ...

  2. C# IO流的操作(一)

    C# IO流的操作非常重要,我们读写文件都会使用到这个技术,这里先演示一个文件内容复制的例子,简要说明C#中的IO操作. namespace ConsoleApplication1 { class P ...

  3. Check access restrictions in Zabbix agent configuration

    配置自定义监控K值时,出现下面错误提示 [root@manage ~]# zabbix_get -s -k "login_user" zabbix_get []: Check ac ...

  4. js生成二维码以及点击下载二维码

    js生成二维码 jquery.qrcode.js可以快速使用页面生成二维码.但改项目有两个小问题:1.不支持中文:2.不支持二维码中间生成图片. 支持中文的jquery-qrcode jquery.q ...

  5. POJ-2353 Ministry(动态规划)

    Ministry Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4761 Accepted: 1528 Special Judg ...

  6. 洛谷P1117 优秀的拆分【Hash】【字符串】【二分】【好难不会】

    题目描述 如果一个字符串可以被拆分为AABBAABB的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串aabaabaaaabaabaa,如果令 A=aabA ...

  7. AjaxAnywhere的用法(FORWARD)

    AjaxAnywhere的用法   ajaxanywhere 总结:1,简介AjaxAnywhere被设计成能够把任何一套现存的JSP组件转换成AJAX感知组件而不需要复杂的JavaScript编码. ...

  8. Oracle备份恢复之Oracle11G R2用exp无法导出空表解决方法

    在11G R2中有个新特性,当表无数据时,不分配segment,以节省空间Oracle当然在执行export导出时,空表则无法导出,但是还是有解决办法的: 解决方法: 一.insert一行,再roll ...

  9. JIRA licence and vulnarability,jenkins,devops

    http://blog.itpub.net/13651903/viewspace-1079918/ http://www.freebuf.com/articles/web/34051.html JIR ...

  10. go语言编程入门

    查看文档 首先先分享一个可以在本地就能查看文档的骚操作(linux系统) 1.打开命令行终端,输入godoc -http=:8000,如果想后台运行在后面加个& 2.然后打开浏览器,输入网址: ...