我在接受采访时被问到这个问题。 他们都是O(nlogn),但大多数人使用Quicksort而不是Mergesort。 这是为什么?
#1楼
在所有条件相同的情况下,我希望大多数人都能使用最方便的东西,而且往往是qsort(3)。 除了快速排序之外,已知数组上的快速排序非常快,就像mergesort是列表的常见选择一样。
我想知道为什么看到基数或桶排序这么罕见。 它们是O(n),至少在链表上,所需要的只是将密钥转换为序数的一些方法。 (字符串和浮点数工作正常。)
我认为原因与计算机科学的教学方式有关。 我甚至不得不向算法分析的讲师证明,确实可以比O(n log(n))更快地排序。 (他有证据证明你不能比O(n log(n))更快地进行比较 ,这是真的。)
在其他新闻中,浮点数可以按整数排序,但您必须在之后转换负数。
编辑:实际上,这是一种更加恶毒的方式来整理浮点数 - 整数: http : //www.stereopsis.com/radix.html 。 请注意,无论您实际使用哪种排序算法,都可以使用位翻转技巧...
#2楼
对于原始值的DualPivotQuickSort带来的变化,答案会略微倾向于快速排序。 它在JAVA 7中用于在java.util.Arrays中进行排序
It is proved that for the Dual-Pivot Quicksort the average number of
comparisons is 2*n*ln(n), the average number of swaps is 0.8*n*ln(n),
whereas classical Quicksort algorithm has 2*n*ln(n) and 1*n*ln(n)
respectively. Full mathematical proof see in attached proof.txt
and proof_add.txt files. Theoretical results are also confirmed
by experimental counting of the operations.
你可以在这里找到JAVA7的实现 - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/java/util/Arrays.java
关于DualPivotQuickSort的更多精彩阅读 - http://permalink.gmane.org/gmane.comp.java.openjdk.core-libs.devel/2628
#3楼
“然而大多数人使用Quicksort而不是Mergesort。为什么会这样?”
没有给出的一个心理原因就是Quicksort更加巧妙地命名。 即良好的营销。
是的,具有三重分区的Quicksort可能是最好的通用排序算法之一,但是没有克服“快速”排序听起来比“合并”排序更强大的事实。
#4楼
快速排序是最坏情况O(n ^ 2),但是,平均情况始终执行合并排序。 每个算法都是O(nlogn),但你需要记住,在谈论Big O时,我们忽略了较低的复杂因素。 当涉及常数因素时,快速排序比合并排序有显着改进。
合并排序还需要O(2n)内存,而快速排序可以就地完成(只需要O(n))。 这是快速排序通常优于合并排序的另一个原因。
额外信息:
当枢轴选择不当时,会发生最快的快速排序。 请考虑以下示例:
[5,4,3,2,1]
如果选择枢轴作为组中的最小或最大数字,则快速排序将在O(n ^ 2)中运行。 选择列表中最大或最小25%的元素的概率为0.5。 这使得算法成为一个良好的支点。 如果我们采用典型的枢轴选择算法(比如选择一个随机元素),我们就有0.5个机会为每个枢轴选择一个好的枢轴。 对于大尺寸的集合,总是选择不良枢轴的概率是0.5 * n。 基于此概率,快速排序对于平均(和典型)情况是有效的。
#5楼
为什么Quicksort好?
- QuickSort在最坏的情况下采用N ^ 2和NlogN平均情况。 最糟糕的情况发生在数据排序时。 在排序开始之前,可以通过随机混洗来减轻这种情况。
- QuickSort不会占用合并排序所需的额外内存。
- 如果数据集很大且项目相同,则Quicksort的复杂性通过使用3路分区而降低。 更多相同的项目更好的排序。 如果所有项目都相同,则按线性时间排序。 [这是大多数库中的默认实现]
Quicksort总是比Mergesort好吗?
并不是的。
- Mergesort稳定但Quicksort不稳定。 因此,如果您需要输出稳定性,则可以使用Mergesort。 在许多实际应用中需要稳定性。
- 记忆现在很便宜。 因此,如果Mergesort使用的额外内存对您的应用程序并不重要,那么使用Mergesort没有任何害处。
注意:在java中,Arrays.sort()函数使用Quicksort作为基本数据类型,使用Mergesort作为对象数据类型。 因为对象消耗了内存开销,所以为Mergesort添加一点开销可能不是性能观点的任何问题。
参考 :观看Coursera的第3周,普林斯顿算法课程的QuickSort视频
来源:oschina
链接:https://my.oschina.net/u/3797416/blog/3183027