按升序或降序排序(任意选择;优先选择哪个更便宜)

时间:2012-11-03 23:13:21

标签: algorithm sorting

我有一系列元素。这个数组可能是:

  • 随机洗牌(约20%的时间)
  • 按升序排序*近似排序*(约占40%的时间)
  • 按降序排序(约占40%的时间)

但我不知道(提前)这些案件中适用哪一种。我更愿意将数组排序为已经接近的顺序。

输出是升序还是降序无关紧要,但它必须是一个或另一个(所以我可以对它进行二分搜索。)

排序不一定稳定。


一些背景信息:过程大致如下:

  • 填充数组
  • 按某些属性A
  • 排序
  • 做一些处理(计算分位数和其他一些小东西)
  • 排序其他属性B
  • 做更多处理
  • 按属性C排序
  • 做更多处理

A和B通常相互关联(但可能是正面或负面的。)同样适用于B和C.偶尔A == C.

*“几乎排序”这里意味着大多数元素都接近其最终位置。但很少完全处于最终位置(存在大量的加性噪声​​,并且没有很多长的排序子序列。)但是,在数组的开始和结束处通常会有一些“异常值”,它们是订单的不良预测因子。下一种。


是否有一种算法可以利用我不喜欢升序与降序的事实,以便更便宜地排序(与我目前正在使用的TimSort相比?)

2 个答案:

答案 0 :(得分:3)

我会继续使用Timsort(但是,一个很好的选择是Smoothsort * ),但首先探测数组以决定是按升序还是降序排序。查看第一个和最后一个元素并进行相应的排序。如果数组未分类,那么选择并不重要;如果(部分)排序,则以较宽的间隔进行探测更有可能正确检测哪种方式。

* Smoothsort具有与Timsort相同的最佳,平均和最差情况时间,以及更好的空间复杂性。与Timsort一样,它专门用于利用部分排序的数据。

答案 1 :(得分:2)

另一种考虑的可能性:

  • 开始进行(手动)插入排序
  • 当你去的时候,计算你执行的倒数数量
  • 完成一些固定数量的小插入操作后,将您计算的反转次数与该点反转的最大反转次数进行比较,如果数据反向排序为:
  • 如果比例接近0,则(可能)数据接近排序。完成插入排序,它对几乎排序的数据执行得非常好。如果你不喜欢“可能”的声音,那么当你走的时候继续计算倒数,如果它低于门槛,你就准备好回到Timsort。
  • 如果比例接近1,那么(可能)数据几乎是反向排序的,并且您在开始时有少量排序元素。将它们移动到最后,将它们反转,并使用反向比较器完成插入排序。
  • 否则数据是随机的,使用您最喜欢的排序算法。我会说Timsort,但是由于这对几乎排序的数据做得很好,必须是一些其他算法,至少比Timsort在统一调整数据上做的要好一点。可能没有Tim的简单合并排序。

“小固定数字”可以是即使在不良情况下插入排序也相当快的数字。我想10-20左右。对于任何给定数量的插入和任何给定阈值“接近0/1”,可以计算出均匀混洗数据中误报的概率,但我太懒了。

你说第一个和最后几个数组元素通常会降低趋势,在这种情况下你可以将它们从初始测试插入排序中排除。

显然,这种方法在某种程度上受到了Timsort的启发。但Timsort针对包含运行的数据进行了极度优化 - 我试图仅针对接近一次大运行(在任一方向上)的数据进行恶魔优化。 Timsort的另一个特点是它经过了很好的测试,我没有声称要分享它。