冒泡排序
int main() {
int a[10] = {10,9,8,7,6,5,4,3,2,1};
int i,j,temp;
for (j=0;j<10;j++) {
for (i=0;i<9;i++) {
if (a[i] > a[i+1]) {
temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
}
}
}
for (i=0;i<10;i++) {
printf("%d ",a[i]);
}
}
的复杂度为O(n ^ 2),因为它有两个O(n)循环,因此O(n)x O(n)。
并且他们说quicksort的复杂性为O(nlog(n))..为什么会这样?
是因为它围绕一个循环划分了一个数字吗?
-Thanks
答案 0 :(得分:9)
没有快速的一句话解释。在最坏的情况下,快速排序实际上是O( n 2 ),但它是O( n log n )平均而言,如果你试图分析它,你将无法证明它总是O( n log n )。平均只有O( n log n ) ,在所有可能的数据集中取平均值。对于任何特定的列表,它可能会更糟。
如果枢轴最终真的非常糟糕,那么快速排序将会非常糟糕。这可能发生在已排序的数据上,例如,如果您始终在数组的开头或结尾选择固定元素作为数据元素。
另一方面,其他排序算法(如合并排序和堆排序)始终为O( n log n )。他们没有病态的情况,他们的表现会降低到O( n 2 )。如果你想要的是始终如一的可预测的性能,这使它们成为可取的。快速排序的优点是总体上算法平均速度更快,但并非总是如此。
编辑:的确,正如 @pst 所说,合并排序在排序数组时需要O( n )空间(合并的临时空间) ),这是不太理想的。这是反对它的观点。但是,另一个反对快速排序的观点是它是一种不稳定的排序。在排序之后,可以混淆彼此相等的元素。
Timsort是一个非常棒的新搜索算法 - 好吧,不那么新,更多是现有算法的完美组合加上大量的微调和聪明的优化(奔腾的事情就是金钱)。阅读该文本文件,了解Great Programming。
答案 1 :(得分:4)
Big-O表示法只是输入值(在您的情况下的元素数量)与复杂性(在您的情况下时间复杂度,van也是空间复杂性)之间的关系。
你对泡泡排序是正确的。因为它在n
次的另一个循环中循环n
次,所以时间复杂度为O(n 2 )。
Quicksort略有不同。它执行了许多依赖于n
的传递,但在每种情况下,它设法将所有值都低于“左”的中点,并且所有值都高于“右”的中点 - 两者一半仍未分类,但你知道 all 左边的元素小于任何的正确元素(让我们称之为枢轴规则)。
这基本上将每个子循环的工作量减半,这导致平均情况O(log n)。与二分搜索或平衡树类似,任何将工作负荷除以每次迭代因子的算法都是O(log n)。
将两者结合起来可以得到O(n log n)。
这个wikipedia page实际上在右上方显示了一个漂亮的小图形,显示了快速排序。由于一张图片胜过千言万语(动画价值千张),你应该看一段时间才能理解。
你会看到它首先将工作区划分为两个,然后在两半之间交换元素,直到满足透视规则。
由于工作负载分为两个完全独立的独立区域,因此快速分配对于并行处理已经成熟,没有资源争用。如果您有足够的处理器,只要将数据分区为两个区域,就可以将每个区域分配给单独的处理器以进行进一步分区。冒泡排序是不可能的,因为那种排序不会给你两个独立的区域。
答案 2 :(得分:2)
查看分析on Wikipedia。
答案 3 :(得分:2)
实际上,quicksort在平均情况下是O(n log(n))。在最坏的情况下,每次都选择最大或最小的元素作为分区,然后执行n +(n -1)+ ... 1 = O(n ^ 2)。
在最好的情况下(平均情况适用于相同的大O),您需要对第一个分区进行比较。这会对大小为n / 2的问题进行两次调用,并且这些调用需要进行n / 2次比较才能进行分区。这继续,所以你得到n + 2 *(n / 2)+ 4 *(n / 4)+ ....总共有log(n)项,每一项都是n,所以整个项都是O(n * log(n))。
正如Thon所说,你可以通过应用Master's定理得到相同的结果,但是你可能值得花些时间手工做一些例子。
答案 4 :(得分:2)
之前的答案描述了quicksort及其运行时间,但我想对最坏情况下的运行时间进行评论。
一般来说,快速排序通常是平均情况下的O(n log n)(给定输入的随机排列)和最坏情况下的O(n ^ 2)。但是,一般来说,quicksort没有指定在每个步骤分配哪个元素,因此当您选择任何元素(通常是第一个或最后一个)作为数据透视而不考虑它的关系时,会出现O(n ^ 2)情况。列表中的其他元素。
您可以通过明智地选择枢轴来实现快速排序以在最坏情况下运行O(n log n)。一种方法是在O(n)时间内找到中值。 (参见http://en.wikipedia.org/wiki/Selection_algorithm#Linear_general_selection_algorithm_-_.22Median_of_Medians_algorithm.22)然后,如果总是围绕中位数进行分区,则检查任何元素的次数最多为O(log n),因此总运行时间为O(n log n)。
答案 5 :(得分:0)
Quicksort是递归的。只需写出伪代码,您就可以轻松地为每个重复的运行时间推导出一个递归公式,然后使用主定理得出最终答案。
答案 6 :(得分:-1)
与此处所有人的观点相反,您的计划的复杂性为O(1)。你还没有定义n是什么。 我知道,我的回答似乎有些愚蠢,但实际上找到问题的界限往往比算法的复杂性更重要。如果您的数据集永远不会超过给定的大小,您可以更好地使用一种具有足够好的性能/行为的简单方法。