【问题标题】:Sorting Networks - which networks allow skipping a comparison?排序网络 - 哪些网络允许跳过比较?
【发布时间】:2017-02-15 17:49:54
【问题描述】:

GCC 对 qsort 的实现使用 3 的中值来选择枢轴。在此过程中,这 3 个元素使用排序网络进行排序。

3 个元素的排序网络通常需要 3 次比较。但是在这个特定的实现中,可以跳过最后一个比较,具体取决于之前的比较:

if(a[0] > a[1]) swap(a[0], a[1]);
if(a[1] > a[2]) swap(a[1], a[2]);
else goto jump;
if(a[0] > a[1]) swap(a[0], a[1]);
jump:;

对于具有n = 4...16 的网络(具有已知的最小最佳比较次数的网络)可以做类似的事情吗?如果是这样,它们会是什么样子?它们会是什么样子?

更新: 到目前为止,我发现了另一个允许跳过一个比较的网​​络:

// sorting network for 5 elements
if (a[0] > a[1]) { SWAP(a[0], a[1]); }
if (a[2] > a[3]) { SWAP(a[2], a[3]); }

if (a[1] > a[3]) { SWAP(a[1], a[3]); }
if (a[2] > a[4]) { SWAP(a[2], a[4]); }

if (a[0] > a[2]) { SWAP(a[0], a[2]); }
if (a[1] > a[4]) { SWAP(a[1], a[4]); }

if (a[1] > a[2]) { SWAP(a[1], a[2]); }
if (a[3] > a[4]) { SWAP(a[3], a[4]); }
else { goto jump; }

if (a[2] > a[3]) { SWAP(a[2], a[3]); }
jump:;

我用 12345 的所有排列对此进行了测试,它对所有排列进行了正确排序。

【问题讨论】:

  • 当您进行条件比较时,如果没有发生交换,那么最终比较将是多余的。您可能可以通过使用第二个原始索引数组并将该数组与数据交换,以及一个大小为 (n^2 - n) / 2 的数组用于可能的比较次数来跟踪哪些元素已经被比较元素(n 个东西,一次取 2 个),初始化为零并为每次比较设置为 1。

标签: sorting sorting-network


【解决方案1】:

撇开最优排序网络不谈,下图显示了一种方法,通过使用大小为 n 的排序网络创建任意大小 n+1 的排序网络,然后执行n 将最后一个元素放置到位的额外比较(这通常是插入排序在转换为排序网络后的工作方式):

与元素 n+1 已经是最大的元素相比,该图像非常明显,那么您可以跳过比较元素 n 之后的每个比较器和n+1。基本上,一旦任何最后一个 n 比较器返回 false,您就可以跳过以下比较器。总体而言,我想说的是,在大多数排序网络中可以跳过比较。

也就是说,一旦你的排序算法中有这样的条件,那么它就不再是一个排序网络,你就会失去排序网络的好处:正确实施时不会出现分支预测问题。

如果您的目标只是用尽可能少的比较和交换对一个小集合进行排序,那么您可以unroll every possible path 一种排序算法,然后为每条路径执行最佳数量的移动/交换,但是这样的方法超过 4 个元素变得完全无法维护,并且您的类型不太可能具有足够昂贵的移动和比较操作来证明这种算法的合理性。

【讨论】:

    猜你喜欢
    • 2014-07-11
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 2018-08-24
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多