【问题标题】:why we are always using quick sort ? or any specific sorting algorithm?为什么我们总是使用快速排序?或任何特定的排序算法?
【发布时间】:2014-01-27 20:12:54
【问题描述】:

为什么我们总是使用快速排序?或任何特定的排序算法??

我在我的电脑上尝试了一些使用快速、合并、堆、闪存排序的实验

结果:-

排序算法:以纳秒为单位的时间 -> 以分钟为单位的时间

快速排序时间:135057597441 -> 2.25095995735

Flash 排序时间:137704213630 -> 2.29507022716667

合并排序时间:138317794813 -> 2.30529658021667

堆排序时间:148662032992 -> 2.47770054986667

在内置函数中使用java

long startTime = System.nanoTime();

给定时间以纳秒为单位,如果我们将它们转换为 20000000 个随机整数数据的秒数,并且 java 中的最大数组大小为 2147483647,那么它们之间几乎没有任何区别。如果我们使用就地算法,那么可能会有 1 到 1 的差异2 分钟直到最大数组大小。

如果差异太小,我们为什么要关心??

【问题讨论】:

  • 好吧,对于初学者来说,sort stability 是有区别的。
  • 这是 one 实现的 one 基准。此外,“我们”并不“总是”使用快速排序;例如 Python 中的标准排序算法是 Timsort,这是一种经过高度修改的归并排序。
  • Mergsort [变体] 在标准库/API 中似乎比快速排序更常见。我在学校离开了快速排序 - 并且更喜欢合并排序的一致保证和稳定性(提示:合并排序与快速排序的 worse 情况是什么?)。另外,请查看梳状排序。
  • 整数的范围是多少?

标签: algorithm


【解决方案1】:

提出的所有算法都有一个相似的平均情况界限,O(n lg n),这是comparison sort 可以做到的“最好”。

由于它们共享相同的平均界限,这些算法在随机数据上的预期性能应该是相似的 - 这就是调查结果所显示的。然而,魔鬼在细节中。这是一个非常快速的总结;点击链接了解更多详情。

Quicksort 一般不稳定(但也有stable variations)。虽然快速排序的平均界限为O(n lg n),但快速排序的最坏情况界限为O(n * n),但有一些方法可以缓解这种情况。与堆排序一样,快速排序就地完成

Merge-sortstable sort。 Mergesort 的最坏情况界限为O(n lg n),这意味着它具有可预测的性能。基本合并排序需要O(n) 额外空间,因此它通常不是就地排序(尽管有一个in-place variant,并且链表实现的内存是恒定的)。

Heapsort不稳定;它还具有O(n lg n) 的最坏情况边界,但具有恒定大小边界和就地的好处。它的缓存和并行性方面比合并排序更差。

究竟哪一个是“最好的”取决于用例、数据和确切的实现/变体。


合并排序(或hybrid such as Timsort)是许多库/语言中的“默认”排序实现。几个 C++ 实现中使用了一个常见的Quicksort-based hybrid, Introsort。 Vanilla/plain Quicksort 实现(如果提供)通常是辅助实现。

合并排序:一种稳定的排序,具有一致的性能和可接受的内存范围。

快速排序/堆排序:简单地就地工作并且[有效地]不需要额外的内存。

【讨论】:

    【解决方案2】:

    我们很少需要对整数数据进行排序。排序的最大开销之一是进行比较所需的时间。快速排序减少了与冒泡排序相比所需的比较次数。如果您正在对字符串进行排序,则这一点更为重要。作为一个真实世界的例子,几年前我写了一个排序/合并,用冒泡排序用了 40 分钟,用快速排序用了 17 分钟。 (很久以前是 z80 CPU。我希望现在性能更好)。

    【讨论】:

    • 增加数据大小和气泡与具有更好边界的排序仍然很重要。因此,这个答案的基础是误导性的。这个问题还询问了不同的排序算法具有相似的性能界限(以及为什么/何时一个比另一个更可取,即使它们都出现“相同的速度”),而不是退化的排序算法。
    • 奥巴马也认为冒泡排序是退化的:youtube.com/watch?v=koMpGeZpu4Q
    【解决方案3】:

    您的结论是正确的:大多数人在大多数情况下都在乎这件事是在浪费时间。这些算法在时间和内存复杂度方面的差异在以下特定场景中变得显着:

    • 你有大量的元素要排序

    • 性能真的很关键(例如:实时系统)

    • 资源确实有限(例如:嵌入式系统)

    (请注意真的

    此外,稳定性问题可能更重要。大多数标准库都提供了稳定的排序算法(例如:C# 中的OrderBy、C++ 中的std::stable_sort、Python 中的sort、Java 中的sort 方法)。

    【讨论】:

    • 如果数据集大部分是排序的,也可能存在巨大差异。
    • @KarolyHorvath 如果我给出的条件都不满足,那也完全无关紧要。在大多数应用程序中,通常还有数百个其他事情需要改进/优化,并且当 n 很小时对第 n 个元素列表进行排序是其中的最后一个,无论它是否主要排序。甚至更多 - 当您有大量记录时,您通常使用数据库,并通过 SQL 对数据进行排序。尽管如此,您还是优化了到数据库的往返次数,而不是排序算法......
    • 好的,那么这是一个更好的选择:当您的系统内存受限时(例如:嵌入式系统) - 您可能需要就地排序。
    • @KarolyHorvath 好点。我有一个时间复杂度,但我省略了内存复杂度。我已将此添加到列表中。
    【解决方案4】:

    正确性。虽然在某些特定场景下切换排序算法可能会提高速度,但证明算法有效的成本可能相当高。

    例如,TimSort 是一种被 Android、Java 和 Python 使用的流行排序算法,它有一个多年未被注意到的实现错误。此错误可能会导致崩溃,并且很容易被用户诱导。

    一个专门的团队“寻找挑战”来isolate and solve这个问题。

    因此,只要数据结构或算法的标准实现可用,我就会使用该标准实现。使用更智能的实现所节省的时间几乎不值得不确定实现的安全性和正确性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-15
      • 2018-05-14
      • 1970-01-01
      • 1970-01-01
      • 2018-03-28
      • 2021-06-19
      • 2013-02-15
      相关资源
      最近更新 更多