当特定的排序算法优于其他算法时,有哪些使用情况 - 归并排序 vs 快速排序 vs 堆排序 vs 'intro sort'等?
是否有建议指南可以根据数据结构的大小、类型、可用内存和缓存以及CPU性能来使用它们?
当特定的排序算法优于其他算法时,有哪些使用情况 - 归并排序 vs 快速排序 vs 堆排序 vs 'intro sort'等?
是否有建议指南可以根据数据结构的大小、类型、可用内存和缓存以及CPU性能来使用它们?
冒泡排序、选择排序:当你需要快速地完成某个任务,但由于某些原因不能使用标准库中的排序算法时,可以考虑使用这两种算法。它们唯一的优点在于比插入排序稍微容易实现一些。
非比较排序:在某些非常有限的情况下,可以打破O(N log N)的时间复杂度下限,并在O(N)的时间内完成排序。以下是一些值得尝试的情况:
计数排序:当你需要对范围有限的整数进行排序时。
基数排序:当log(N)远大于基数位数K时(其中K是基数位数),可以考虑使用基数排序。
桶排序:当你可以保证输入数据近似均匀分布时,可以考虑使用桶排序。
快速排序通常是平均速度最快的,但它在最坏情况下的表现相当糟糕。因此,如果您需要保证没有糟糕的数据导致O(N^2)
,则应避免使用它。
归并排序使用额外的内存,但特别适合外部排序(即不适合内存的大型文件)。
堆排序可以原地排序,并且没有最坏情况的二次方行为,但在大多数情况下平均速度比快速排序慢。
在只涉及到限定范围内的整数时,您可以使用某种基数排序来使其非常快。
在99%的情况下,您可以使用库排序,这些排序通常基于快速排序,可以满足需求。
@dsimcha 写道: 计数排序:当您对具有有限范围的整数进行排序时
我会改成:
计数排序:当您对正整数进行排序时(0-Integer.MAX_VALUE-2,由于鸽洞原理)。
您始终可以在线性时间内获取最大值和最小值作为效率启发式方法。
此外,您需要至少n个额外空间用于中间数组,它显然是稳定的。
/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
尽管实际上它允许到MAX_VALUE-2,但是请注意: Java数组有最大大小吗?
此外,我想解释一下基数排序的复杂度是O(wn),其中n个键是大小为w的整数。有时w被表示为一个常数,这将使基数排序比所有执行O(n log n)比较以对n个键进行排序的最佳基于比较的排序算法更好(对于足够大的n)。然而,通常情况下,w不能被视为常数:如果所有n个键都不同,则为了能够将它们存储在内存中,随机访问机器的w至少必须为log n,这会给出最好的时间复杂度O(n log n)。(来自维基百科)