timsort和quicksort的比较
为什么当timsort(根据维基百科)似乎performance更好时,我主要听说quicksort是最快的整体sortingalgorithm? 谷歌似乎没有任何比较。
TimSort是高度优化的mergesort,比旧的mergesort更稳定,更快。
与quicksort相比,它有两个好处:
- 对于接近sorting的数据序列(包括反向sorting数据),这是快得难以置信的;
- 最坏的情况仍然是O(N * LOG(N))。
说实话,我不认为#1是一个优势,但它确实给我留下了深刻的印象。
这是QuickSort的优势
- QuickSort非常简单,即使是经过高度调整的实现,我们也可以在20行内写下它的pseduo代码;
- QuickSort在大多数情况下是最快的;
- 内存消耗是LOG(N)。
目前,Java 7 SDK实现了timsort和一个新的快速sorting变体:即Dual Pivot QuickSort。
如果你需要稳定的sorting,试试timsort,否则以quicksort开始。
或多或less,这与Timsort是一个混合sortingalgorithm有关。 这意味着虽然它使用的两种底层sorting(Mergesort和Insertionsorting)对于多种数据都比Quicksort差,但Timsort只有在有利时才使用它们。
在稍微深入的层面上,正如Patrick87所说的,快速sorting是最差的O(n 2 )algorithm。 select一个好的支点并不困难 ,但是保证O(n log n)快速sorting的代价是平均sorting通常较慢。
有关Timsort的更多详细信息,请参阅此答案和链接的博客文章。 它基本上假定大部分数据已经部分sorting,并构造了sorting数据的“运行”,允许使用mergesort进行高效合并。
一般来说quicksort是基本数组的最佳algorithm。 这是由于内存局部性和caching。
JDK7使用TimSort for Object数组。 对象数组只保存对象引用。 对象本身存储在Heap中。 为了比较对象,我们需要从堆中读取对象。 这就像从堆的一部分读取一个对象,然后从堆的另一部分随机读取对象。 会有很多caching未命中。 我猜这是因为内存局部性不再重要。 这可能是为什么JDK只使用TimSort for Object数组而不使用基本数组。
这只是我的猜测。
下面是我的机器(i7-6700 CPU,3.4GHz,Ubuntu 16.04,gcc 5.4.0,参数:SIZE = 100000和RUNS = 3)的基准数字:
$ ./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
基准来自Swenson的sorting项目,他在C中实现了几种sortingalgorithm。可以推测 ,他的实现已经足够代表性,但是我没有对它们进行调查。
所以你真的不知道。 基准数字只在最多两年内保持相关,然后您必须重复。 当问题被问到时,可能timsort在2011年打败了waaay,但是时代已经改变了。 或qsort总是最快,但timsort击败非随机数据。 或者Swenson的代码不太好,一个更好的程序员会在timsort的帮助下扭转局面。 或者,也许我吮吸,编译代码时没有使用正确的CFLAGS
。 或者…你明白了。