我在一次面试中被问到这个问题。它们都是O(nlogn),但大多数人使用快速排序而不是归并排序。为什么呢?
当前回答
在所有条件相同的情况下,我希望大多数人使用最方便的方法,这往往是qsort(3)。除此之外,快速排序在数组上非常快,就像归并排序是列表的常用选择一样。
我想知道的是为什么基数排序和桶排序这么少见。它们是O(n)至少在链表上是这样的它所需要的只是将键转换为序数的方法。(字符串和浮动工作得很好。)
我认为原因与计算机科学的教学方式有关。我甚至不得不向我的讲师演示算法分析,它确实有可能比O(nlog (n))更快地排序。(他证明了比较排序不能比O(nlog (n))快,这是正确的)
在其他新闻中,浮点数可以按整数排序,但之后必须将负数反转。
编辑: 实际上,这里有一种更糟糕的将浮点数作为整数排序的方法:http://www.stereopsis.com/radix.html。注意,不管你实际使用什么排序算法,比特翻转技巧都可以使用……
其他回答
与归并排序不同,快速排序不使用辅助空间。而归并排序使用辅助空间O(n)。 归并排序的最坏情况时间复杂度是O(nlogn)而快速排序的最坏情况复杂度是O(n²)这发生在数组已经排序的时候。
虽然它们都在相同的复杂度类中,但这并不意味着它们都具有相同的运行时。快速排序通常比归并排序更快,因为它更容易编写紧凑的实现代码,它所做的操作也更快。这是因为快速排序通常更快,人们使用它而不是归并排序。
然而!我个人经常会使用归并排序或快速排序变体,当快速排序表现不佳时,它们会降级为归并排序。记住。快速排序平均只有O(n log n)最坏情况是O(n²)归并排序总是O(n log n).在实时性能或响应性是必须的情况下,你的输入数据可能来自恶意来源,你不应该使用简单的快速排序。
在c/c++领域,当不使用stl容器时,我倾向于使用快速排序,因为它是构建的 进入运行时,而归并排序没有。
所以我相信,在许多情况下,这只是阻力最小的途径。
此外,对于整个数据集不适合工作集的情况,快速排序的性能可以高得多。
正如许多人所注意到的,快速排序的平均情况性能要比归并排序快。但这只适用于假设按需访问任何内存段的时间为常数的情况。
在RAM中,这种假设通常不太坏(由于缓存的存在,这种假设并不总是正确的,但也不太坏)。然而,如果你的数据结构足够大,可以存储在磁盘上,那么快速排序就会因为磁盘平均每秒进行200次随机查找而被扼杀。但是,同样的磁盘在按顺序每秒读取或写入兆字节的数据方面没有任何问题。这正是归并排序所做的。
因此,如果数据必须在磁盘上排序,你真的,真的想使用归并排序的一些变体。(通常你快速排序子列表,然后开始将它们合并到某个大小阈值以上。)
Furthermore if you have to do anything with datasets of that size, think hard about how to avoid seeks to disk. For instance this is why it is standard advice that you drop indexes before doing large data loads in databases, and then rebuild the index later. Maintaining the index during the load means constantly seeking to disk. By contrast if you drop the indexes, then the database can rebuild the index by first sorting the information to be dealt with (using a mergesort of course!) and then loading it into a BTREE datastructure for the index. (BTREEs are naturally kept in order, so you can load one from a sorted dataset with few seeks to disk.)
在许多情况下,了解如何避免磁盘寻道使我将数据处理工作花费数小时而不是数天或数周。
但大多数人使用快速排序而不是归并排序。为什么呢?”
一个没有给出的心理学原因是,快速排序的名字更为巧妙。很好的市场营销。
是的,带有三重分区的快速排序可能是最好的通用排序算法之一,但“快速”排序听起来比“归并”排序强大得多,这是无法克服的事实。