java arratlist sort_Java.util.ArrayList.sort()排序算法

我正在看grepcode上java.util.ArrayList的sort()方法的源代码。 他们似乎在小数组(大小<7)上使用插入排序,在大数组上使用合并排序。 我只是想知道这是否有很大的不同,因为它们仅对大小小于7的数组使用插入排序。在现代计算机上,运行时间的差异几乎不会引起注意。

我在科门读过:

Although merge sort runs in O(n*logn) worst-case time and insertion sort runs in O(n*n) worst-case time, the constant factors in insertion sort can make it faster in practice for small problem sizes on many machines. Thus, it makes sense to coarsen the leaves of the recursion by using insertion sort within merge sort when subproblems become sufficiently small.

如果我已经为我需要的某些组件设计了排序算法,那么我会考虑在插入时间与合并排序相比变得明显之前,将插入排序用于更大的大小(可能小于100)。

我的问题是,得出小于7的大小背后的分析是什么?

The difference in running time will be hardly noticeable on modern machines.

当您意识到总体排序算法是递归的时,对小数组进行排序所花费的时间变得非常重要,而小数组排序实际上是该递归的基础情况。

我没有关于如何选择第七名的任何内部信息。但是,如果由于在小阵列上对竞争算法进行基准测试,然后选择最佳算法和阈值而没有这样做,我会感到非常惊讶。

附言值得指出的是,Java7默认使用Timsort。

我现在有点你的意思了。假设如果我们有一个非常大的数组,则对它进行递归排序将把该数组分成许多小的数组。我猜这就是插入排序的效率提高的地方。

@ sultan.of.swing:是的。

是的,我认为这回答了我的问题。除了我需要分析基准测试结果以相信选择大小七的概念:)

@ sultan.of.swing:如果您确实愿意,可以轻松地将排序代码复制并粘贴到自己的项目中,并运行一些基准测试。 :)

我不知道我的这一页面是否对讨论感兴趣:javamex.com/tutorials/collections/

@NeilCoffey您的页面确实非常有帮助。它可以很好地洞察我正在寻找的性能数据排序。感谢分享 :)

我将其发布给那些将来访问此线程并记录我自己的研究成果的人。我偶然发现了这个极好的链接,以寻找选择7之谜的答案:

蒂姆·彼得斯(Tim Peters)对算法的描述

您应该阅读标题为"计算minrun"的部分。

要给出要点,minrun是数组的截止大小,在该大小以下,算法应开始使用插入排序。因此,我们将始终对大小为" minrun"的数组进行排序,我们将需要在该数组上运行合并操作以对整个数组进行排序。

在java.util.ArrayList.sort()中," minrun"被选择为7,但是据我对上述文档的理解,它打破了神话,并表明它应接近2的幂且小于256。并超过8。引用该文档:

At 256 the data-movement cost in binary insertion sort clearly hurt, and at 8 the increase in the number of function calls clearly hurt. Picking some power of 2 is important here, so that the merges end up perfectly balanced (see next section).

我要说明的是," minrun"可以是小于64的2的幂(或接近2的幂),而不会影响TimSort的性能。

为什么可能是64?在一直要求分析的线程中如此模糊不清似乎很奇怪。

@EJP我不是故意要含糊。链接的文档很好地解释了该概念。但我认为您是正确的,我会稍作修改。

http://en.wikipedia.org/wiki/提姆索尔

" Timsort是一种混合排序算法,是从合并排序和插入排序派生而来的,旨在对多种现实世界数据表现良好。该算法查找已排序的数据子集,并使用这些子集对通过合并一个已识别的子集(称为运行)与现有运行,直到满足特定条件,才能完成此操作。"

关于数字7:

" ...而且,可以看出,仅当初始元素不是另一个运行的前七个元素之一时,舞动才是有益的。这也导致MIN_GALLOP设置为7。为避免舞动模式的弊端,合并函数会调整min-gallop的值,如果该元素来自当前正在考虑的数组(即,连续连续返回元素一段时间的数组),则min-gallop的值将减一。时,该值增加1,因此不鼓励您回到疾驰模式,这样做的话,在随机数据的情况下,min-gallop的值变得很大,以致从未发生过疾驰模式。

在使用merge-hi的情况下(也就是说,合并是从右到左完成的),舞动需要从数据的右端开始,即最后一个元素。从一开始就疾驰也可以得到所需的结果,但是进行的比较却超出了所需。因此,用于奔腾的算法包括使用变量,该变量给出了开始奔腾的索引。因此,该算法可以在任何索引处进入舞动模式并如上所述继续运行,因为它将在下一个索引处进行检查,该索引偏移了1、3、7,...,(2k-1)。和以目前的索引为准。如果是merge-hi,则索引的偏移量将为-1,-3,-7,...。

我看不到使用插入排序的最小运行次数(OP问题)与合并期间从同一次运行中获取的元素数量之间的任何关系,这些触发触发疾驰模式(您的答案)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值