这里我使用伪代码来表示我的算法,它是 DFS 的变体
编码风格模仿算法简介,每当我们遇到一个顶点时,它的颜色都是 BLACK 。假设起始顶点是 START ,目标顶点为 TARGET ,图形表示为 G =(V,E)。更多的事情,假设图形已连接,并且连接牢固如果它是有向图。
FIND-ALL-PATH(G,START,END)
for each vertex u in G.V
u.color=WHITE
path=0//store the result
DFS-VISIT(G,START)
DFS-VISIT(G,u)
if(u==TARGET)
path=path+1
return
u.color=BLACK
for each v in G:Adj[u]
if(v.color==WHITE)
DFS-VISIT(G,v)
u.color=WHITE;//re-paint the vertex to find other possible ways
如何分析上述算法的时间复杂度?如果它是正常的DFS那么当然是O(N + E),因为每个顶点只访问一次,并且每个边都被访问了两次。但是这个怎么样呢?似乎很难指定每个顶点或边被访问的时间。
答案 0 :(得分:1)
要分析FIND-ALL-PATH
的时间复杂度,让我们看一下DFS-VISIT
的时间复杂度。我假设您使用邻接列表来表示图形。
在这里,在DFS-VISIT
的一次调用中,连接到u
的每个顶点(作为参数传递的顶点)将被探索一次(即顶点颜色将被更改为黑色)。由于这是一个递归函数,所以在每次递归中都会形成一个新的堆栈,每个堆栈中存在的集合G:Adj[u]
只不过是与u
相邻的元素。因此,所有列表中的每个节点将被一起检查(颜色被改变)一次,并且每当检查它们时,我们进行一致的工作(即O(1)操作)。在有向图的情况下存在总体E元素,而在邻接列表表示中的无指向图的情况下存在2E。所以我们说它的时间是O(E),其中E
是边数。在一些书中,他们增加了额外的时间O(N),其中N
是顶点的数量,因此他们说DFS-VISIT
的总时间复杂度是O(N + E)(我认为额外O(N)时间的原因是for循环执行N
次或者可能是其他的东西)。顺便说一句,N
始终小于E
,因此您可以忽略它或考虑它,它不会影响DFS-VISIT
的渐近时间。
函数FIND-ALL-PATH
的时间复杂度为 NFS时间复杂度DFS-VISIT ;其中N
是图表中顶点的数量。所以我会说你上面写的算法与深度优先遍历算法不完全相同,但它会做与深度优先遍历相同的工作。您的算法所花费的时间更多,因为您为图表中的每个顶点调用了DFS-VISIT
。您的函数FIND-ALL-PATH
可以在调用DFS-VISIT
函数之前进行优化,只需检查顶点的颜色是否更改为BLACK
(这通常是在深度优先级中完成的)遍历)。
即你应该写下这样的函数:
FIND-ALL-PATH(G,START,END)
for each vertex u in G.V
u.color=WHITE
path=0//store the result
for each vertex u in G.V
if u.color is WHITE
DFS-VISIT(G,START)
现在,上面写的这个函数与DFS-VISIT
具有相同的时间复杂度。
另请注意,将所有顶点的颜色初始化为WHITE需要一些时间,即O(N)操作。
因此,函数FIND-ALL-PATH
的总体时间复杂度为 O(N)+ O(N *(N + E)),或者您可以忽略第一个O(N) (因为它与其他术语相比非常少。)
因此,时间复杂度= O(N *(N + E)),或者如果您假设DFS-VISIT
函数只有O(E)时间,那么您可以说时间复杂度 O(N * E)。
如果您对上述任何一点有疑问,请告诉我。