Algorithm 按升序或降序排序(任意选择;以较便宜的为准)
我有一个元素数组。此阵列可以是:Algorithm 按升序或降序排序(任意选择;以较便宜的为准),algorithm,sorting,Algorithm,Sorting,我有一个元素数组。此阵列可以是: 随机洗牌(大约20%的时间) 几乎按升序排序*(大约40%的时间) 几乎按降序排序(大约40%的时间) 但我(事先)不知道这些案例中哪一个适用。我更愿意将数组排序为它已经接近的顺序 输出是升序还是降序并不重要,但它必须是一个或另一个(因此我可以对其执行二进制搜索) 这类产品不一定要稳定 一些背景信息:过程大致如下: 填充数组 按某个属性排序 做一些处理(计算分位数和其他一些次要的东西) 按其他属性B排序 做更多的处理 按属性C排序 做更多的处理 A和B
- 随机洗牌(大约20%的时间)
- 几乎按升序排序*(大约40%的时间)
- 几乎按降序排序(大约40%的时间)
一些背景信息:过程大致如下:
- 填充数组
- 按某个属性排序
- 做一些处理(计算分位数和其他一些次要的东西)
- 按其他属性B排序
- 做更多的处理
- 按属性C排序
- 做更多的处理
是否有一种算法可以利用我不喜欢升序或降序的事实,以更便宜的方式进行排序(与我目前使用的TimSort相比?我会继续使用TimSort(但是,一个好的替代方法是*),但首先探测数组以决定是按升序还是降序排序。查看第一个和最后一个元素,并相应地进行排序。如果数组未排序,则选择无关紧要;如果它是(部分)排序的,则以较宽的间隔进行探测更有可能正确检测哪种方式
*Smoothsort与Timsort具有相同的最佳、平均和最坏情况时间,并且具有更好的空间复杂度。与Timsort一样,它是专门为利用部分排序的数据而设计的。考虑的另一种可能性:
- 开始执行(手动滚动)插入排序
- 当你走的时候,数一数你做的倒转的次数
- 在完成少量固定数量的插入后,将已计算的反转数与该点发生的最大反转数进行比较,前提是首先对数据进行反向排序:
- 如果比例接近0,则(可能)数据几乎已排序。完成插入排序,它在几乎排序的数据上执行得非常好。如果你不喜欢“可能”的声音,那么继续计算倒数,如果倒数低于某个阈值,准备返回Timsort
- 如果比例接近1,那么(可能)数据几乎是反向排序的,并且在开始时有少量已排序的元素。将它们移到末尾,反转它们,并使用反转比较器完成插入排序
- 否则数据是随机的,请使用您喜欢的排序算法。我想说的是Timsort,但由于它在几乎排序的数据上做得很好,所以肯定有其他算法比Timsort在均匀无序数据上做得至少好一点点。可能是没有Tim的简单合并排序
显然,这种方法在某种程度上受到了Timsort的启发。但是Timsort对包含运行的数据进行了恶魔般的优化——我尝试过只对接近一次大运行的数据进行恶魔般的优化(在任何方向)。Timsort的另一个特点是,它经过了很好的测试,我不想与大家分享。+1(尽管“几乎排序”可能意味着什么,所以可能需要探测两个以上的边界元素)对您的原理感到好奇,即探测更宽的间隔更有可能探测到排序方向…@Groo-确实如此。也许比较第一个k元素和最后一个k元素。然而,在某种程度上,决定订单的成本开始成为一个重要因素;请注意,如果您使用自己的Timsort,您可以在收集minruns时决定降序/升序。@Triptych-这只是基于OP对数据可能受到干扰的描述的一种启发式方法。这个顺序与前面的排序“相关”,这对我来说意味着更大的间距更有可能检测到趋势(如果有)。有什么原因你不能预先计算索引吗?@Triptych:它们会很短。通常,在丢弃数组之前,每个排序属性只使用一次(仅保留“执行处理”步骤的结果)