Grokking Timsort

时间:2009-11-14 02:52:19

标签: java python algorithm sorting timsort

在块上有一个(相对)新的排序名为Timsort。它被用作Python的list.sort,现在将成为the new Array.sort in Java 7

some documentationtiny Wikipedia article描述排序的高级属性和一些低级别的性能评估,但我很好奇是否有人可以提供一些伪代码来说明Timsort正在做什么,确切地说,以及使它变得活泼的关键因素是什么。 (参见引用的论文“乐观排序和信息理论复杂性”。)

(另见related StackOverflow post。)

2 个答案:

答案 0 :(得分:14)

从现已删除的博文中引用相关部分:Visualising Sorting Algorithms: Python's timsort

  

timsort的业务端是一个mergesort,它运行预先排序的元素。选择最小游程长度minrun以确保最终合并尽可能平衡 - 对于64个元素,minrun恰好是32.在合并开始之前,通过数据进行单次传递以检测已存在的已排序运行元素。通过简单地将它们反转就可以处理降序运行。如果得到的运行长度小于minrun,则使用插入排序将其提升到minrun。在没有重要预先存在的运行的混洗数组上,此过程看起来与我们上面的猜测完全相同:在使用合并排序合并之前,使用插入排序预先排序minrun元素块。

[...]

  • timsort找到降序运行,并在原地反转运行。这是直接在指针数组上完成的,因此从我们的观点来看似乎是“即时”。
  • 现在使用插入排序将运行提升到minrun长度。
  • 在下一个块的开头没有检测到运行,并且插入排序用于对整个块进行排序。请注意,此块底部的已排序元素未经过特殊处理 - timsort不会检测在块被提升为minrun的过程中开始的运行。
  • 最后,mergesort用于合并运行。

答案 1 :(得分:8)

当它进入时,这个变化经历了core-libs mailing list,所以那里有一些讨论和有用的链接。以下是web rev代码审核更改以及original patch

代码中的评论说:

  

实施说明:此实施是稳定的,自适应的    迭代合并,需要远远少于n lg(n)的比较    当输入数组部分排序时,同时提供
   当输入数组为
时,传统mergesort的性能    随机排序。如果输入数组几乎排序,则    实施需要大约n次比较    临时存储要求从近似分类的小常数变化    输入数组到n / 2个对象引用,用于随机排序的输入
   阵列。

     

实施同样有利于提升和支持    在其输入数组中降序,并可以利用
   在同一个不同部分的升序和降序    输入数组。它非常适合合并两个或多个排序数组:
   简单地连接数组并对结果数组进行排序    该实现是根据Tim Peters的Python列表排序改编的    TimSort。它使用了Peter McIlroy的“乐观”中的技术    “排序与信息理论复杂性”,载于“论文集”    第四届年度ACM-SIAM离散算法研讨会,第467-474页,第4页    1993年1月。

埋没在very useful link to the Python implementation details,我认为这是一个很好的起点,然后是代码。要想达到令人难以置信的高水平,timsort会通过注意排序数据的运行并在排序过程中利用该结构来提高性能。