思想:对于最新发现的顶点v,若是它还有以此为起点而还未探索的边,沿此边探索。若是v的全部边已经探索完了,再回溯到发现v有起始点的那些边。一直到已经探索了从源起点可到的全部顶点为止。若是还有没探索的顶点,将它定义为一个新的源顶点,继续上述过程。算法
像走迷宫同样,尝试每种可能的结果,没走通,就回溯到当初分叉的路口,继续探索bash
DFS(V,Adj):
parent={}
for s in V: //遍历图中全部的点
if s not in parent: //点没有遍历过就继续探索
parent[s]=None //源点不设置父节点
DFS-Visit(Adj,s) //探索当前源顶点可以到达的全部的点
复制代码
DFS-Visit(Adj,s):
for v in Adj[s]: //遍历全部的边
if v not in parent: //当前边没有遍历过
parent[v]=s //记录已经遍历
DFS-Visit(adj,v) //优先探索当前节点的边,完成以后,再执行回溯(经过循环实现)
复制代码
以有向图为例
假设按照字母的顺序来遍历全部的顶点,即V=[a,b,c,d,e,f],原始的图为spa
深度优先树指的是通过DFS生成的树,结果为3中的橙色箭头所指的两个部分.net
O(V+E);它的遍历规则仍然须要遍历全部的节点一遍,对于每条变来说,只有没有遍历过的才作一次遍历3d
在算法中,树边判断经过parent就能够看出,parent的逆向就是树边,得以标识;code
反边判断,能够在源点开始作一个标记,把全部的通过的节点都放入栈中,若是下次获得的顶点在栈中,那么这条边就是反边;cdn
图G存在环,当且仅当图中存在一条反边。证实以下:blog
Job自己是个无环的有向图,各个顶点之间一定存在着必定的顺序,执行的时候等前面的执行完才能再执行排在后面的排序
它使用的算法称做拓扑排序,拓扑排序内部使用的就是DFS,输出为完成时的顶点的逆序,就排序好了(以前记录的是parent的指向,真正的执行是先parent)it
这种排序产生的结果是,假设图中全部的顶点放在同一个水平线上,那么全部的方向均是从左到右
证实
只须要证实,对于任何一个边e=(u,v),在v执行完以后,u才执行完
算法导论(MIT 6.006 第14讲)