【问题标题】:Running time analysis of brute force BFS vs Dijkstra's for shortest path algorithm蛮力 BFS 与 Dijkstra 最短路径算法的运行时间分析
【发布时间】:2019-06-27 04:28:31
【问题描述】:

Dijkstra 的运行时间为 O(|E| + |V|log|V|) 蛮力 BFS 的运行时间为 O(|E| + |V|)

那么为什么 dijkstra 更优呢?好像运行时间比较长。

编辑:请参阅标记的答案。事实证明,我在加权图上使用 BFS 对最短路径的运行时间分析(基本上是蛮力)是不正确的。在加权图上使用蛮力 BFS 的上限为 O(V!)。 Dijstra 的更佳。

【问题讨论】:

标签: algorithm


【解决方案1】:

我假设您的意思是暴力破解所有路径组合并选择最快的。但这需要您(可能)使用指数级的 BFS,在这种情况下,您不能说时间复杂度为 O(|V|+|E|)。 O(|V|+|E|) 是如果您使用 BFS 的时间量是恒定的。我提到了 2 个图表示例,以说明您必须证明 Dijkstra 比蛮力 BFS 更快的路径的可能性数量,因为后者取决于您拥有多少路径的可能性。

平衡二叉树,有一个根(起点),每个顶点都有 2 个子节点,除了叶子节点和作为叶子节点之一的目标顶点。如果从根目录开始,则路径有 2 种选择。如果你去其中一个,你还有另外 2 个选择,依此类推,直到你到达目标顶点。这使得 2 * 2 * ... * 2 路径可能性,其中它乘以 log(|V|)-1 倍。这是O(n)。这使得蛮力 BFS 算法的运行时间为 O(n^2 + nm),比 Dijkstra 慢。

全图:假设你从 V1 开始,目的地是 Vn,你可以从 V1 开始,下一个顶点有 V-1 个可能性。在第二个顶点你有 V-2 的可能性,在第三个 V-3 等等,直到你在 Vn。这使得 V-1 * V-2 * ... * 3 * 2 * 1 = O((V-1)!) 可能的路径数,这使蛮力 BFS 算法具有指数运行时间。

我们可以将后者视为上限。下界可以是一个图,它是一条路径,两种算法都需要 O(n) 时间。我们可以得出结论,可能在所有情况下,Dijkstra 都比蛮力 BFS 算法更快或一样快。

【讨论】:

  • 如何对蛮力 BFS 进行运行时间分析?就像如果每对顶点都有一条边,那么运行时间应该是 O(V^V),因为每个顶点都可以连接到其他顶点。但是如果每对顶点都没有边怎么办。你如何确定蛮力运行时间?
  • 这真的取决于你的图表的样子。让我们考虑一个有 n 个顶点的二叉树(在这种情况下很容易确定运行时间)。如果你从根开始,你有两个选择(左孩子或右孩子)。如果你选择其中一个,选项就会翻倍,你有 4 种可能性,依此类推,直到你完成了整棵树。这使得 2*2*2*2....*2 log2(n) 次。所以这会产生 O(n) 路径,您需要使用 BFS O(n) 次。现在该算法的运行时间将变为 n*(n+m) = n^2 + nm,这比 Dijkstra 差很多。
  • 对于一般图表,我不知道如何计算其中路径数的公式(如果有办法做到这一点,我会感到惊讶)。但是,如果 bruteforce BFS 解决方案使像二叉树这样的简单图的运行时间为 n^2 + nm,那么 Dijkstra 可能对任何图都快得多。
  • 对于一般图,假设每个顶点平均有 k 条边和 N 个顶点。这将是k ^ N。我的分析正确吗?换句话说,二叉树只是一个平均有 2 条边的图,运行时间为 2^N。如果是全连接图,则为 N^N,因为每个顶点有 N 条边
  • 不,例如对于二叉树(平衡),从根到叶有 O(n) 条路径。 O(n) 因为 2^(log(n)-1) = O(n) 因为树的高度不是 n,而是 log(n)。但是对于从根到叶的路径,对于其他对,您的路径较少。对于每个顶点正好有 K 个孩子的树,你有 K^(log(n)-1),它应该又是 O(n)。也许我关于可能性指数数量的说法不正确,但蛮力算法仍然比 Dijkstra 慢。
【解决方案2】:

Dijkstra 的运行时间为 O(|E| + |V|log|V|),但它可以在 加权 图中找到源节点和目标节点之间的最短路径。 BFS 的运行时间为O(|E| + |V|),但它仅在所有边具有相等权重 时才能找到源节点和目标节点之间的最短路径。如果你所有的边缘都具有相同的权重,那么确实不需要运行 Dijkstra。

【讨论】:

  • 我试图理解为什么不能使用 BFS 进行加权图搜索。假设每次都跟踪当前的路径成本总和,并且我不断探索每一个我尝试所有可能的路线组合。我最终可以找到 BFS 的最短路径吗?没有?
  • @samol:你当然可以用这种方式扩展 BFS,但它不会再有 O(|E| + |V|) 的最坏情况运行时间。 Plain BFS 每个节点只访问一次,因为第一次访问是最短路径,所以可以将节点标记为已访问,之后跳过。如果你每次找到一个低转换路径时都添加逻辑来重新访问一个节点,它会变得很多更昂贵。 Dijkstra 算法的最坏情况 O(|E| + |V| log |V|) 版本只是带有最小堆而不是队列的 BFS,这让它支持加权边,同时仍然只需要访问每个节点一次。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-08
  • 2014-10-16
  • 1970-01-01
  • 2016-07-30
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多