【问题标题】:Incorrect Pivot Selection for Sort Algorithm排序算法的枢轴选择不正确
【发布时间】:2020-11-16 04:30:09
【问题描述】:

我正在尝试实现"Comparison Based Sorting for Systems with Multiple GPUs" 论文中概述的多 GPU 排序算法。

该算法依赖于以下关键见解(第 5 页):

给定两个排序数组 A_α 和 A_β,在 A_β 中存在一个枢轴点 P,在 A_α 中存在其“镜像”对应点 P',将输入数组分为上下两部分,使得来自两个下部都小于或等于两个上部的元素,而每个数组下部的元素数等于另一个数组上部的元素数。合并下部和合并上部将产生两个排序数组,当它们连接时提供一个排序数组。

我已经在 C++ 中实现了枢轴选择功能(如第 6 页的伪代码所述)。

size_t SelectPivot(const std::vector<int> &a, const std::vector<int> &b)
{
  size_t pivot = a.size() / 2;
  size_t stride = pivot / 2;
  while (stride > 0)
  {
    if (a[a.size() - pivot - 1] < b[pivot])
    {
      if (a[a.size() - pivot - 2] < b[pivot + 1] &&
          a[a.size() - pivot] > b[pivot - 1])
      {
        return pivot;
      }
      else
      {
        pivot = pivot - stride;
      }
    }
    else
    {
      pivot = pivot + stride;
    }
    stride = stride / 2;
  }
  return pivot;
}

但是,对于某些输入(随机选择的数据),选择的枢轴似乎偏离了 1(或者对于大型输入来说明显更多)。使用地板、隐藏或增加枢轴的几个快速修复仅解决了某些输入的问题,因此不提供通用解决方案。

Sorted partitions:
1 3 5 7 9 11 14 16 18 20 22 24 26 | 0 2 4 6 8 10 12 15 17 19 21 23 25 

Pivot:
8

Swapped partitions:
1 3 5 7 9 0 2 4 6 8 10 12 **15** | **11** 14 16 18 20 22 24 26 17 19 21 23 25 

有人知道如何解决一般情况下的问题吗?

【问题讨论】:

    标签: c++ algorithm sorting c++11


    【解决方案1】:

    我认为这段代码应该这样做。我们希望找到最大的pivot &gt; 0 使得a[a.size() - pivot] &gt;= b[pivot - 1]a 的最小上元素大于或等于b 的最大下元素),或者0,如果不存在这样的枢轴。由于pivot 是最大可能的,这意味着pivot == b.size()a 的最小元素大于或等于b 的最大元素)或a[a.size() - 1 - pivot] &lt; b[pivot]a 的最大下元素小于最小上元素b 的元素)。

    #include <cassert>
    #include <iostream>
    #include <vector>
    
    using ::std::size_t;
    
    size_t SelectPivot(const std::vector<int> &a, const std::vector<int> &b) {
      assert(a.size() == b.size());
      size_t low = 0;
      size_t high = b.size();
      while (low < high) {
        size_t mid = high - (high - low) / 2;
        if (a[a.size() - mid] < b[mid - 1]) {
          high = mid - 1;
        } else {
          low = mid;
        }
      }
      return low;
    }
    
    int main() {
      std::cout << SelectPivot({1, 3, 5, 7, 9, 11, 14, 16, 18, 20, 22, 24, 26},
                               {0, 2, 4, 6, 8, 10, 12, 15, 17, 19, 21, 23, 25})
                << '\n';
    }
    

    【讨论】:

    • 非常感谢!它可以工作,并且更容易理解,因为它更类似于二分搜索。
    猜你喜欢
    • 1970-01-01
    • 2010-09-14
    • 2017-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-23
    • 2015-01-13
    • 2022-10-12
    相关资源
    最近更新 更多