如果我的想法错了,请纠正我。我认为BigO(V + E)= BigO(V ^ 2)。
以下是我的想法:
完整图中的边= = *(n-1)/ 2。
从E和V切换到n,因为我更容易这样思考。
E = n *(n-1)/ 2
V = n
BigO(V + E)=> BigO(n + n *(n-1)/ 2)=> BigO(n ^ 2)
将n切换回V。
=>戈(V ^ 2)
我错过了什么吗?为什么要使用BigO(V + E)?为什么不使用BigO(V ^ 2)?答案 0 :(得分:4)
邻接列表的内存使用量与节点数和边数之和成正比。这是因为每个节点具有离开它的边缘的相关列表,并且每个边缘最多出现两次(对于在无向图中触摸的每个节点一次,或对于有向图一次)。这意味着空间使用率为Θ(V + E)。
你在内存使用上给出了两个不同的渐近界限:O(V + E)和O(V 2 )。这两个边界都是正确的,但一个比另一个更紧。 O(V + E)界限更准确地表明有两个半独立量进入空间使用,节点数和边数,并且更精确。 O(V 2 )界限不太精确,但通过考虑E的最大可能值(以V为单位)给出总内存使用情况的最坏情况界限。换句话说,O(如果你试图精确地确定内存使用量,那么V + E)绑定会更有用,但是如果你担心最坏情况的内存,O(V 2 )的界限会更好的使用。
(快速说明:声明“邻接列表是O(V + E)”并不是一个有意义的句子。由于big-O量化了函数的增长率,它就像是说“邻接列表是95,201” “ - 它没有意义,因为你将一个对象与一个数字进行比较。但是,你可以说”邻接列表的空间使用是O(V + E)“,因为邻接列表的空间使用是一个实际的数字量。 )
答案 1 :(得分:0)
BigO用于根据输入大小估算您将使用多少<time, memory, whatever resource>
。
当您构建邻接列表时,您知道顶点数V
和边数E
。现在你想估计你需要多少内存。
O(V+E)
可以解释为V > E ? O(V) : O(E)
含义:它与max(V,E)
线性复杂。
您为每个v创建一个列表,因此您可以使用O(V)
内存。
您标记每个边缘,这使用O(E)
内存。 O(V+E)
就是这个意思。如果您认为复杂度为O(V^2)
,则意味着对于具有2*n
顶点的空图表,您应该使用约。与4
顶点的空图形相比,n
时间更多。
在对复杂性进行一些研究时,您可以测试不同的方法:
如果您希望收到更多信息,请阅读有关该主题和评论的不同方法。
修改强>
根据正式定义,O(V+E)
,O(V^2)
,O(V^3)
和O(V^V^V)
仍然是正确的。在BigO
中,我们尝试找到效率最慢的函数,但仍然是BigO
的复杂性。
答案 2 :(得分:0)
这两个陈述都是正确的。它们并不矛盾。
在任意图上,资源使用为O(V 2 )。但是在可能存在稀疏图的问题域中,资源使用是O(V + E)。这提供了更多信息。
邻接列表通常用于图表可能稀疏的问题域中。对于密集图,阵列通常是更好的解决方案。如果您正在考虑两种可能的算法来解决图形问题,则需要考虑您对图形的了解。学位是否受到限制?在这种情况下,邻接列表表示和相关算法可能是更好的解决方案。
复杂性分析不仅仅是一种理论游戏。这是一种组织您对实际编程问题的实际解决方案的思考的方法。