想象一下可以排序的所有可能的事物数组。可以说它们是长度为“n”的数组,并忽略诸如具有一个元素的数组之类的东西(当然,它们总是已经排序。
想象一下该数组的所有可能值组合的长列表。请注意,我们可以稍微简化一下,因为数组中的值总是有某种排序。因此,如果我们用数字 1 替换最小的一个,用 1 或 2 替换下一个(取决于它是否相等或更大)等等,我们最终会遇到相同的排序问题,就好像我们允许任何值一样。(这意味着长度为 n 的数组最多需要数字 1-n。如果一些相等,可能会更少。)
然后在每个数字旁边放一个数字,说明用其中的值对该数组进行排序需要多少工作。你可以放几个数字。例如,您可以输入所需的比较次数。或者,您可以输入所需的元素移动或交换次数。无论你放什么数字都表明它需要多少次操作。你可以把它们加起来。
您必须做的一件事是忽略任何特殊信息。例如,您无法提前知道数组中值的排列是否已经排序。您的算法必须对该数组执行与任何其他数组相同的步骤。(但第一步可能是检查它是否已排序。不过,通常这对排序没有帮助。)
所以。通过比较测量的最大数字是当值以病态错误方式排列时的典型比较次数。同样,最小的数字是当值以非常好的方式排列时所需的比较次数。
对于冒泡排序,最好的情况(最短或最快)是值是否已经有序。但这只有在您使用标志来判断您是否交换了任何值时。在最好的情况下,您查看每对相邻的元素一次,发现它们已经排序,当您到达最后时,您发现您没有交换任何东西,所以您已经完成了。这是总共 n-1 次比较,是您可以进行的最少比较次数。
我需要一段时间才能弄清楚最坏的情况。几十年来我没有看过冒泡排序。但我猜这是他们被逆序排列的情况。您进行第一次比较并发现第一个元素需要移动。与每个元素相比,您向上滑动到顶部,最后将其与最后一个元素交换。因此,您在那一关中进行了 n-1 次比较。第二遍从第二个元素开始,进行 n-2 次比较,依此类推。因此,在这种情况下,您进行 (n-1)+(n-2)+(n-3)+...+1 比较,大约为 (n**2)/2。
也许您对冒泡排序的变体比我描述的要好。不管。
那么对于冒泡排序,下限为 n-1,上限为 (n**2)/2
其他排序算法有更好的性能。
您可能要记住,除了比较之外,还有其他操作需要花费。我们使用比较是因为很多排序都是用字符串完成的,而且字符串比较在计算时间上是昂贵的。
您可以使用元素交换来计数(或交换和元素交换的总和),但它们通常比与字符串的比较短。如果你有数字,它们是相似的。
您还可以使用更深奥的东西,例如分支预测失败或内存缓存未命中或进行测量。