【发布时间】:2017-10-13 10:45:24
【问题描述】:
还有其他关于冒泡排序时间复杂度的问题,但这个问题不同。每个人都说冒泡排序最坏的情况是 O(n^2)。在列表的 i 次迭代后的冒泡排序中,列表的最后 i 个元素是有序的,不需要再次触摸或比较。如果您一次又一次地不必要地遍历最终元素,时间复杂度只会是 O(n^2)。
鉴于冒泡排序的一个主要特征是(输入大小减去迭代)之后的元素永远不需要再次比较,因为它在正确的位置,为什么说冒泡排序的时间复杂度是对我来说,我不认为是冒泡排序?即使在维基百科中,它也说时间复杂度是 O(n^2),然后只在文章的中途提到它可以“优化”到仅花费大约 50% 的时间,而不是不必要地比较最后 i 个元素。
我被提醒了这一点,因为我正在创建一个循环来检查世界上所有对象的碰撞,并且模式是我检查过的:
for (int i = 0; i < numberofobjects - 1; i++)
{
{
for (int iplusone = i + 1; iplusone < numberofobjects; iplusone++)
// check collision between i and iplusone
}
}
对于 400 个对象,O(n^2) 的时间复杂度为 400 * 400 = 160,000。然而,它只进行了 79,800 次比较,大约 50%,这正是维基百科所说的。这让我想起了冒泡排序,所以当我检查时,我很惊讶地看到每个人都说它是 O(n^2)。
这是否意味着每当有人提到冒泡排序时,他们指的是在已经排序的最终元素上不必要地重复的版本?此外,当比较不同的算法时,冒泡排序总是表现更差,但作者指的是明显糟糕的 n^2 版本吗?
【问题讨论】:
-
Gauss sez:
Sum(i = 1, n){i} = (n^2+n)/2最高项是n^2。 -
所有冒泡排序变体都是 O(n^2)。这只是意味着比较的数量随着 n^2 的增长而增长,具有一定的比例和恒定的偏移量。因此,如果您对 100 个元素进行排序,您将执行大约 10,000 次比较。它可能是一半,也可能是两倍,但它仍然以二次方的形式增长。
-
@Tom Karzes 我明白了,所以它实际上并没有说明特定实例的任何内容,只是它如何增长?这似乎没那么有用。此外,当您说您将执行大约 10,000 次比较时,如果您使用我正在考虑的冒泡排序,则不是这样。
-
一半或两倍都没有关系,它仍然会增长为 n^2。如果将输入大小加倍,则运行时间将增加 4 倍。如果将输入大小增加 10 倍,则运行时间将增加 100 倍。 O(n^2)、O(0.5*n^2)、O(2*n^2)都是一样的,大家都用O(n^2)来表示。这是您想要的度量,因为它可以让您快速估计在可接受的时间内您可以处理多大的数据集。
-
不是常数因子无所谓,只是在极限情况下被增长相形见绌。最简单的排序算法是 O(n^2)。最快的排序算法是 O(nlog(n))。现在假设你的慢速算法经过高度优化,只需要 0.5*n^2,而你的快速算法优化很差,需要 2*nlog(n)。现在看看 n 为 1000 时的复杂度:慢速算法需要 0.5*1000*1000 = 500,000,而快速算法需要 2*1000*10 = 20,000,所以它快了 25 倍(我在这里保守地使用 log2) .并且随着 n 的增长,该比率不断增长。
标签: c time-complexity big-o bubble-sort