std :: sort来排序数组和索引列表?

时间:2012-11-28 16:28:24

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

我有一个函数,它接受两个与参数大小相同的向量:

void mysort(std::vector<double>& data, std::vector<unsigned int>& index)
{
   // For example :
   // The data vector contains : 9.8 1.2 10.5 -4.3
   // The index vector contains : 0 1 2 3
   // The goal is to obtain for the data : -4.3 1.2 9.8 10.5
   // The goal is to obtain for the index : 3 1 0 2
   // Using std::sort and minimizing copies
}

如何解决最小化所需副本数量的问题?

一种显而易见的方法是制作std::pair<double, unsigned int>的单个向量,并通过[](std::pair<double, unsigned int> x, std::pair<double, unsigned int> y){return x.first < y.first;}指定比较器,然后将结果复制到两个原始向量中,但效率不高。

注意:函数的签名是固定的,我不能传递std::pair的单个向量。

5 个答案:

答案 0 :(得分:6)

在函数内部,创建一个向量positions = [0,1,2,3...] 使用比较器(int x, int y){return data[x]<data[y];}对位置进行排序。

然后迭代位置,执行result.push_back(index[*it]);

这假设index中的值可以是任意的。如果保证已经像您的示例中那样[0,1,2..],那么您不要制作positions数组,只需在其中使用index并跳过最后一个副本。

答案 1 :(得分:2)

http://www.boost.org/doc/libs/1_52_0/libs/iterator/doc/index.html#iterator-facade-and-adaptor

std::pair<double&, signed int&>上编写一个迭代器,它实际上将一对迭代器包装到每个向量中。唯一棘手的部分是确保std::sort意识到结果是随机访问迭代器。

如果您不能使用boost,请自行编写等效文件。

在此之前,确定是否值得你打扰。压缩,排序和解压缩更容易编写,程序员时间可以在很多地方交换性能:直到你知道最佳花费的地方,也许你应该做一个足够好的工作,然后在你需要的地方进行基准测试加快速度。

答案 2 :(得分:1)

您可以使用仿函数类来保存对值数组的引用,并将其用作比较器来对索引数组进行排序。然后将值复制到新值数组并交换内容。

struct Comparator
{
    Comparator(const std::vector<double> & data) : m_data(data) {}
    bool operator()(int left, int right) const { return data[left] < data[right]; }
    const std::vector<double> & m_data;
};

void mysort(std::vector<double>& data, std::vector<unsigned int>& index)
{
    std::sort(index.begin(), index.end(), Comparator(data));
    std::vector<double> result;
    result.reserve(data.size());
    for (std::vector<int>::iterator it = index.begin(), e = index.end();  it != e;  ++it)
        result.push_back(data[*it]);
    data.swap(result);
}

答案 3 :(得分:1)

您可以使用自定义迭代器类,它并行迭代两个向量。其内部成员将由

组成
  1. 两个引用(或指针),每个向量一个
  2. 指示当前位置的索引
  3. 迭代器的值类型应为pair<double, unsigned>。这是因为std::sort不仅会交换项目,还会在某些情况下临时存储单个值。我在this question的第3部分中详细介绍了这一点。

    引用类型必须是某个类,它再次保存对向量和当前索引的引用。因此,如果您小心,可以使引用类型与迭代器类型相同。引用类型的operator=必须允许从值类型进行赋值。并且swap函数应该专门用于此引用,以允许通过单独交换两个列表来交换这些列表项。

答案 4 :(得分:-1)

这应该这样做:

std::sort(index.begin(), index.end(), [&data](unsigned i1, unsigned i2)->bool
{ return data[i1]<data[i2]; });

std::sort(data.begin(), data.end());