递归 DFS 的复杂性
Complexity of a recursive DFS
希望这是一个简单的问题,但我似乎找不到答案。
据称DFS的时间复杂度是O(|V|+|E|)
。现在我有问题看到为什么它取决于边缘的数量。我看到的通常解释如下:
假设我们使用显式堆栈实现 DFS(为简单起见)。假设我们有一个图表,其中每个节点都连接到所有其他节点。我们从某个节点开始,访问它然后将它的所有邻居推入堆栈。现在我们弹出下一个节点并将它的所有邻居放入堆栈。我们重复,直到我们访问所有节点。
让我们假设在每次迭代中尚未访问位于堆栈顶部的节点(此图的最佳情况)。在这种情况下,我们访问了 |V|
移动中的所有节点,但是对于每个节点,我们将 |V|-1
个节点压入堆栈,这意味着所有边都被压入堆栈,复杂度为 O(|E|)
一些注意事项。我认为复杂性比这要低,所以这个只看最坏情况图的最佳场景的证明很好。我还假设 |E|
总是大于 |V|
。事实上,我假设它是 O(|V|^2)
。这意味着 O(|V|+|E|)
和 O(|E|)
对我来说意义相同。
好的,现在我的交易来了。如果我们不使用显式堆栈怎么办?
这里的爆炸是因为我们一直在堆积永远不会被处理的无用节点。如果我们只是递归呢?好处是我们可以在每次递归调用之前检查是否完成。
由于没有明确的堆栈,而且我仍然只访问以前从未见过的节点,所以我看不出如何能超过 O(|V|)
的复杂性。
The explosion here is due to the fact that we keep stacking up useless nodes that will never be processed. What if we instead just recurse? The advantage is that we can check if we're done before each recursive call.
该检查仍然有助于 运行 时间。对于您访问的每个节点,您需要查看它的哪些邻居仍然需要访问,这意味着检查每个相邻的边。
希望这是一个简单的问题,但我似乎找不到答案。
据称DFS的时间复杂度是O(|V|+|E|)
。现在我有问题看到为什么它取决于边缘的数量。我看到的通常解释如下:
假设我们使用显式堆栈实现 DFS(为简单起见)。假设我们有一个图表,其中每个节点都连接到所有其他节点。我们从某个节点开始,访问它然后将它的所有邻居推入堆栈。现在我们弹出下一个节点并将它的所有邻居放入堆栈。我们重复,直到我们访问所有节点。
让我们假设在每次迭代中尚未访问位于堆栈顶部的节点(此图的最佳情况)。在这种情况下,我们访问了 |V|
移动中的所有节点,但是对于每个节点,我们将 |V|-1
个节点压入堆栈,这意味着所有边都被压入堆栈,复杂度为 O(|E|)
一些注意事项。我认为复杂性比这要低,所以这个只看最坏情况图的最佳场景的证明很好。我还假设 |E|
总是大于 |V|
。事实上,我假设它是 O(|V|^2)
。这意味着 O(|V|+|E|)
和 O(|E|)
对我来说意义相同。
好的,现在我的交易来了。如果我们不使用显式堆栈怎么办?
这里的爆炸是因为我们一直在堆积永远不会被处理的无用节点。如果我们只是递归呢?好处是我们可以在每次递归调用之前检查是否完成。
由于没有明确的堆栈,而且我仍然只访问以前从未见过的节点,所以我看不出如何能超过 O(|V|)
的复杂性。
The explosion here is due to the fact that we keep stacking up useless nodes that will never be processed. What if we instead just recurse? The advantage is that we can check if we're done before each recursive call.
该检查仍然有助于 运行 时间。对于您访问的每个节点,您需要查看它的哪些邻居仍然需要访问,这意味着检查每个相邻的边。