我的一位朋友最近提到,你可以通过“缩短它”来减少合并排序的实际运行时间。他没有将数组分解为各个块,而是提到应该停止在各个数组大小等于缓存行大小的位置,因为整个数组将被加载到缓存中。此时,您应该使用替代排序(即插入排序)来合并每个阵列,然后完成合并排序。
虽然BigO建议不然,但他的建议似乎具有直观意义。有人可以确认或否认这一点,和/或提供有关其工作原理和原因的更多信息吗?
感谢帮助人员!
答案 0 :(得分:0)
嗯,(有点抽象)答案是Big-O只对大数字有用:它抛弃了常数因子:O(n)= O(3n),抛出低阶项:O(n² + 3N)= O(N²)。所以是的,你无法用Big-O表示法来判断。
此外,Big-O表示法通常用于一个非常简单的模型,其中每个“操作”只花费1,而且它不知道缓存。
这就是为什么模型没有告诉你这可能有用。我想你可以看看Donald E. Knuth的“排序和搜索”,在那里他用虚构的汇编语言对运行时分析进行了较低的术语(但仍然不考虑缓存,IIRC)。
答案 1 :(得分:0)
插入排序组合创建小运行,然后切换到合并排序称为timsort。维基文章:
答案 2 :(得分:0)
使用 O (Ω,Θ等)分析复杂性仅用于描述算法如何作为输入执行规模增长。如果查看实际函数,可以看到随着输入的增长,常数因子变得不那么重要了。总的来说,输入大小占主导地位。
在实践中,常数因素确实很重要(缓存未命中,指令延迟等等),这就是为什么RadixSort通常很少使用的原因。例如,从寄存器读取大约需要从缓存中最低级别读取的时间的1/5(大约是下一级别的1/5等等)。由于它们是数量级的,实际上缓存成本通常主导算法的实际性能。
插入排序确实可以非常有效地使用缓存,通常只要数据适合缓存。由于它是连续的,它也与预测器很好地相互作用。两者都是为什么对较小的投入更好的原因。另一个很好的例子是QuickSort,它在技术上是O(n^2)
,但在实践中仍然使用很多,因为它具有更好的缓存特性。 TimSort(Python和Java的默认值)也对较小的输入使用插入排序。