【问题标题】:Efficient algorithm of partial sorting into N unsorted groups部分排序为 N 个未排序组的高效算法
【发布时间】:2014-10-24 23:24:23
【问题描述】:

我正在寻找一种有效的算法来执行以下操作:给定一个包含 N 个项目的数组,以某种方式对其进行排序,以便项目作为 M 个相等的组出现,其中每个组未排序,但组在彼此之间排序(一组中的所有元素都小于下一组中的任何元素)。

最简单的方法是对整个数组进行排序。但它效率低下,尤其是当组数远小于项目总数时(例如,将一百万个项目分为 5 个组)。

目前我已决定使用quickselect 算法(具体来说,它是Floyd-Rivest variation)将一个数组排序为2 个未排序的组,然后将其应用M-1 次。一个显着的改进可能是对快速选择应用分而治之的方法,首先将数组分为两组,然后对每一半进行排序,等等,直到我们有 M 个组。 unordered partial sorting 问题的一种概括。

但我有一种直觉,可能有一种更简单、更有效的方法来解决这个问题。有什么我想念的吗?有任何想法吗?我需要这个来提高我的RBush JavaScript library(一种高效的 R*-tree 实现)中的批量插入性能。

【问题讨论】:

    标签: algorithm sorting partitioning selection-sort quickselect


    【解决方案1】:

    这里是对问题的重述。您需要同时找到 M-1 个排序的元素,并使用它们将数组分成 M 个未排序的组。

    我建议从标准快速选择开始,随机枢轴选择接近中位数(使用随机子样本技巧来估计),对于每种情况,将数组分成 2,您还需要找到 2 的排名元素列表。继续此操作,直到您可以在当前组中找到排名元素的级别。然后切换到快速选择的 Floyd-Rivest 变体以实际找到该元素并将当前组拆分为 2 个。然后退出快速选择,您可以轻松地将 M 个您想要的组拼凑在一起。

    这种方法的预期运行时间为O(N log(M)),具有相当不错的常数。我怀疑这明显比这更好。

    【讨论】:

    • 听起来很棒!
    • 所以如果我理解正确的话,它可以通过运行一个类似快速排序的传递(当你在两侧而不是一侧递归)来查找所有排名元素,对吗?然后你会对排序的元素进行排序并在每个排序的元素索引上运行分区子例程,从而产生我需要的未排序组数组?
    • @Mourner 甚至比这更简单。您可以在快速选择的底部找到排名元素,但不需要它们。您只需要知道左侧和右侧的组是什么。但是在查找排序元素的过程中,您最终会为从一个点到另一个点的元素生成大量的数组分区。在退出的路上,你知道每个分区应该进入哪些未排序的组。因此,您向下递归以定位排名元素,并在退出递归解决方案的过程中将您正在寻找的组拼凑在一起。
    • 嗯...鉴于我需要以我想要的方式重新排序原始数组,看起来在我找到所有排序的元素之后,数组将已经正确分类成组而无需任何额外的在出去的路上工作——对吧?
    • 将 2x more swaps 注释划掉——实际上交换和比较的次数要少一些,但对于小数字 M(比如 4),性能会慢 20%。对于 M = 32,它大约快 30%。不过,我没想到它会在任何数字上变慢......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 2011-10-21
    相关资源
    最近更新 更多