使用三个数字比较器进行排序

Sorting using a three number comparator

本文关键字:比较器 数字 排序 三个      更新时间:2023-10-16

>我有一个大小为 n 的数组等待排序。但与普通的排序问题不同,我不得不使用特定的比较器,它接收三个数字并告诉三个数字的最大值和最小值。我的目标是在对数组进行完全排序之前尽可能少地使用比较器。我可以使用什么策略?

感谢您的任何帮助!

由于您的三路比较器可以通过对普通比较器的三次调用来实现,这意味着我们不能将任何正态排序算法改进超过 3 倍。一个更仔细的论证表明,因为每个三向比较都给了我们 log₂ 6 ≈ 2.585 位的信息,我们不能改进超过这个数字。直观地说,当使用普通比较器排序时,您可能会比较a <= bb <= c,因此无论如何都不需要比较ac;因此,可能的加速系数可能小至 2。

因此,渐近地,我们仍在寻找O(n logn(算法,问题是如何利用比较器进行至少2倍的比较。首先要尝试的"明显"事情是修改现有的基于比较的排序算法;一个很好的候选者是自下而上的堆排序,它在平均情况下进行大约 n 个 log₂ n 比较,在最坏的情况下进行 1.5 n 个 log₂n的比较(维基百科(。这击败了标准的快速排序算法,该算法在平均情况下进行大约 1.39 n logn比较(维基百科(。

该算法在堆上使用两个基本操作,"筛选"和"筛选"。

  • "筛选"操作需要将父元素与其两个子元素进行比较,以查看父元素是否大于或等于其两个子元素,或者如果不是,则应与哪个子元素交换父元素。我们可以使用三路比较器同时比较父母和两个孩子。
  • "筛选"操作将子节点与其父节点进行比较,如果子节点顺序不正常,则交换它们;然后一直重复此操作,直到根节点。我们可以使用三向比较器将子节点与其父节点和祖节点同时进行比较。

堆排序算法仅在这两个操作中调用比较器,对于这两个操作,三向比较器的调用次数可以减少 2 倍。这不一定是你能做的最好的事情,但它从一个非常有效的算法开始,并与直觉给出的最坏情况加速系数相匹配。

嗯,我想出了一个主意。

让我们记住快速排序的工作原理:

  • 首先,我们找到一种中值(如果你太懒了,(a[0] + a[N-1])/2拿起=3(。
  • 然后,我们划分一个数组 在小于或大于中位数的条件下由 2 。
  • 最后,我们在两个子数组中的每一个递归运行算法

使用比较器,您可以通过一次处理两个值来加快第二阶段的两倍:

  • compare(median, a[2 * i], a[2 * i + 1])
  • 如果 min 是中位数,则两者都更大并转到正确的子数组
  • 如果 max 是中位数,则两者都较小并转到左侧子数组
  • 如果两者都不是中位数,则最小值向左,Max 向右

之后,像往常一样运行算法的递归部分。

好吧,我有一个绝妙的主意。根据我的粗略估计,使用 4 路合并排序和失败者树进行优化,使用比较器的次数可以减少到 0.5nlog₂n 以下。