[英]Complexity of a recursive function that counts paths in graph
我找到了一个有向图的函数,该函数针对其中的顶点“ u”和“ v”,计算从“ u”到“ v”的所有可能的走行,且走行上恰好有k条边。 代码和算法来自这里 。 所以,
// C++ program to count walks from u to v with exactly k edges
#include <iostream>
using namespace std;
// Number of vertices in the graph
#define V 4
// A naive recursive function to count walks from u to v with k edges
int countwalks(int graph[][V], int u, int v, int k)
{
// Base cases
if (k == 0 && u == v) return 1;
if (k == 1 && graph[u][v]) return 1;
if (k <= 0) return 0;
// Initialize result
int count = 0;
// Go to all adjacents of u and recur
for (int i = 0; i < V; i++)
if (graph[u][i]) // Check if is adjacent of u
count += countwalks(graph, i, v, k-1);
return count;
}
我试图找到并证明该算法的复杂性。 根据帖子:
“上述函数的最差情况时间复杂度是O(V ^ k),其中V是给定图中顶点的数量。我们可以通过绘制递归树来简单地分析时间复杂度。最坏情况发生在完整图上。在最坏的情况是,递归树的每个内部节点将恰好有n个子节点。”
但是,我找不到找到可以分析的树的递归,以证明该算法为O(V^k)
。 另外,我认为最好的情况是Theta(1)
。 真的吗? 一般情况如何?
对于完整的图形,每个节点都相互连接,因此for
循环将使|V|
递归调用。 这将在每个递归调用中发生,直到k
变为1,因此总共O(|V|^k)
递归调用。
您可以这样表达:
T(V, k) = |V|*T(V, k - 1)
= |V|*|V|*T(V, k - 2)
= |V|^2*|V|*T(V, k - 3)
= ...
它始终为T(V, _)
因为可以多次访问一个节点。
最好的情况确实是O(1)
,如果在第一个调用期间触发条件,则前三个条件之一将被触发。
我不确定一般情况,但我认为仍然应该很糟糕。 考虑一个链表图和一个巨大的k
:为了使k
变为0或1,您将多次移动相同的边。随着添加更多路径,这种情况会变得越来越糟。
通用“平均案例”分析在这样的问题中有点不适,因为您可以选择如何定义“随机”图。 一种方法是说,对于0 <= p <= 1,每个可能的边都以概率p出现,然后尝试根据p分析平均案例运行时间。 但是,还有其他方法可以定义随机图。 同样,平均案例分析通常很困难。 但是,如果您定义“平均”的含义(即,表示随机图的含义),则有人可能会对此表示怀疑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.