Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm timsort与quicksort的比较_Algorithm_Sorting_Quicksort_Timsort - Fatal编程技术网

Algorithm timsort与quicksort的比较

Algorithm timsort与quicksort的比较,algorithm,sorting,quicksort,timsort,Algorithm,Sorting,Quicksort,Timsort,为什么我经常听说快速排序是最快的整体排序算法,而Timsort(根据)的性能似乎要好得多?谷歌似乎没有进行任何比较。或多或少,这与这是一种混合排序算法有关。这意味着,虽然它使用的两种底层排序(Mergesort和Insertion sort)都比许多类型的数据更糟糕,但Timsort仅在这样做有利时才使用它们 在稍深一点的层次上,如前所述,快速排序是最坏情况下的O(n2)算法。选择一个好的pivot并不重要,但是保证一个O(n logn)快速排序的代价通常是平均排序速度较慢 有关Timsort的

为什么我经常听说快速排序是最快的整体排序算法,而Timsort(根据)的性能似乎要好得多?谷歌似乎没有进行任何比较。

或多或少,这与这是一种混合排序算法有关。这意味着,虽然它使用的两种底层排序(Mergesort和Insertion sort)都比许多类型的数据更糟糕,但Timsort仅在这样做有利时才使用它们

在稍深一点的层次上,如前所述,快速排序是最坏情况下的O(n2)算法。选择一个好的pivot并不重要,但是保证一个O(n logn)快速排序的代价通常是平均排序速度较慢


有关Timsort的更多详细信息,请参阅和链接的博客文章。它基本上假设大多数数据已经部分排序,并构造排序数据的“运行”,从而允许使用mergesort进行高效合并。

TimSort是高度优化的mergesort,它比旧的mergesort稳定且速度更快

与快速排序相比,它有两个优点:

  • 对于几乎排序的数据序列(包括反向排序的数据),它的速度令人难以置信
  • 最坏的情况仍然是O(N*LOG(N))
  • 老实说,我不认为1是一个优势,但它确实给我留下了深刻的印象

    以下是QuickSort的优点

  • QuickSort非常简单,即使是经过高度调优的实现,我们也可以在20行内写出它的psedoo代码
  • 在大多数情况下,快速排序是最快的
  • 内存消耗为LOG(N)
  • 目前,Java7SDK实现了timsort和一个新的快速排序变体:即双枢轴快速排序


    如果您需要稳定排序,请尝试timsort,否则从快速排序开始。

    一般来说,快速排序是基本数组的最佳算法。这是由于内存位置和缓存造成的

    JDK7对对象数组使用TimSort。对象数组仅保存对象引用。对象本身存储在堆中。要比较对象,我们需要从堆中读取对象。这就像从堆的一部分读取一个对象,然后从堆的另一部分随机读取对象。将有很多缓存未命中。我想正是因为这个原因,内存位置不再重要了。这可能就是为什么JDK只对对象数组使用TimSort,而不是if基元数组


    这只是我的猜测。

    以下是我机器的基准数字(i7-6700CPU,3.4GHz,Ubuntu 16.04,gcc 5.4.0,参数:大小=100000,运行次数=3):

    基准测试来自Swenson的项目,在该项目中,他用C实现了几个排序算法。据推测,他的实现足够好,具有代表性,但我还没有对它们进行研究


    所以你真的不知道。基准数据最多只能维持两年,然后你必须重复它们。也许,蒂姆索特在2011年被问到这个问题时击败了qsort waaay,但时代已经改变了。或者qsort总是最快的,但是timsort在非随机数据上胜过它。或者说斯文森的代码不太好,一个更好的程序员会让潮流向蒂姆索特靠拢。或者我很糟糕,在编译代码时没有使用正确的
    CFLAGS
    。或你明白了

    如果您需要保留顺序的排序,或者如果您正在对复杂数组(比较基于堆的对象)而不是基本数组进行排序,那么Tim Sort非常有用。正如其他人所提到的,quicksort从基本阵列的数据和处理器缓存的局部性中获益匪浅

    提出了快速排序的最坏情况是O(n^2)这一事实。幸运的是,在最坏的情况下,使用快速排序可以实现O(n log n)时间。当轴点是最小值或最大值时,例如当轴是已排序数组的第一个或最后一个元素时,会发生快速排序最坏情况

    我们可以通过将枢轴设置为中值来实现O(n logn)最坏情况下的快速排序。因为求中值可以在线性时间O(n)内完成。由于O(n)+O(n logn)=O(n logn),这将成为最坏情况下的时间复杂度


    然而,在实践中,大多数实现都发现随机数据透视就足够了,所以不要搜索中值。

    因为人们选择忽略快速排序是O(n^2)最坏的情况。一个可能的答案是:你找错人了。但是,正如另一个答案已经暗示的那样:qsort要古老得多,所以它在更多的库中使用——而且你知道:永远不要碰正在运行的系统。如果平均运行时间(意思是:在使用它的人的用例中)不比一个不同算法(如timsort)的运行时间差很多,那么人们太懒(或者有更好的事情要做)而不是去改变某些东西,那么在同一时间也会这样做。在某些应用程序中(例如python),timsort已经是默认值了。@Patrick87:事实上大不相同。您忽略了O(n)最佳情况。这并不是说最坏的情况基本上永远不会发生,而是最好的情况实际上会发生。timsort在遇到排序范围时做得很好。@RobNeuhaus:我认为(一个简单的实现)快速排序的最坏情况实际上经常发生。只需对已经(几乎)排序的列表进行排序。@MartinThoma排序的列表只会对非常糟糕的快速排序实现产生最坏的结果。三个分区选择实现的随机或中位数避免了排序或近似排序列表的最坏情况。但它们仍然没有实现Timsort的O(n)行为。Timsort的稳定性也是人们忽视的一个关键属性。它在很多情况下都非常有用,尤其是在多键排序时。#1可能是一个巨大的优势。如果您维护一个必须频繁重新排序的数据列表(因为项目被插入、追加或修改),那么使用一种算法可以非常便宜地重新排序该数据是非常有用的。当然,它是否有用取决于具体情况,但在某些ca中它是巨大的
    $ ./demo 
    Running tests
    stdlib qsort time:                 12246.33 us per iteration
    ##quick sort time:                  5822.00 us per iteration
    merge sort time:                    8244.33 us per iteration
    ...    
    ##tim sort time:                    7695.33 us per iteration
    in-place merge sort time:           6788.00 us per iteration    
    sqrt sort time:                     7289.33 us per iteration    
    ...
    grail sort dyn buffer sort time:    7856.67 us per iteration