c - 为什么冒泡排序时间复杂度被称为 n 平方?

标签 c time-complexity big-o bubble-sort

<分区>

关于冒泡排序时间复杂度的问题还有其他问题,但这个问题不同。每个人都说冒泡排序的最坏情况是 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 版本吗?

最佳答案

With 400 objects a time complexity of O(n^2) would be 400 * 400 = 160,000. However it only did 79,800 comparisons, roughly 50%

是的,关于 79,800 次比较,你是对的,但你没有很好地理解大 O 符号。

首先,如果你仔细观察冒泡排序算法,你会注意到确切的步骤比较是:

n-1 + n-2 + ... + 1 = n(n-1)/2 exactly

这意味着当 n=400 时,您将得到正好 400*399/2=79,800 次比较

虽然大 O 表示法告诉您总步骤是:n(n-1)/2 = n^2/2 - n/2 并且在大 O 表示法中我们忽略低阶项和常数,我们只保留 n^2 所以它是 O(n^2)

这里您需要了解的是,大 O 表示法并没有告诉您确切的步骤,它只是告诉您一个上限,例如复杂度函数的高阶,这是针对 n 上的大值。它只是声明 “对于大 n,增长的复杂度阶数是 c*n^2” - 它描述了当参数趋向于 a 时函数的限制行为特定值或无穷大。

关于c - 为什么冒泡排序时间复杂度被称为 n 平方?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46728083/

相关文章:

将字节反转的 uint64_t 复制到 uint8_t 数组

algorithm - 查找只能被 2、3 和 5 整除的前 N ​​个数字的时间复杂度

data-structures - 从通用数据结构中进行索引,插入和删除的时间复杂度是多少?

c - 从文件读入结构

c - 寻找孪生素数 - 逻辑已完成,但程序运行时不会打印任何内容

c++ - C 程序可移植性

algorithm - 为什么链表的长度属性为 O(n)

algorithm - 以下表达式的时间复杂度是多少?

big-o - 估计执行计算所需的操作数

python - 是否有 numpy 库的大 O 复杂性列表?