我有一个函数,它接受两个与参数大小相同的向量:
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
的单个向量。
答案 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)
您可以使用自定义迭代器类,它并行迭代两个向量。其内部成员将由
组成迭代器的值类型应为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());