我写了一个通用版本的索引排序。
template <class RAIter, class Compare>
void argsort(RAIter iterBegin, RAIter iterEnd, Compare comp,
std::vector<size_t>& indexes) {
std::vector< std::pair<size_t,RAIter> > pv ;
pv.reserve(iterEnd - iterBegin) ;
RAIter iter ;
size_t k ;
for (iter = iterBegin, k = 0 ; iter != iterEnd ; iter++, k++) {
pv.push_back( std::pair<int,RAIter>(k,iter) ) ;
}
std::sort(pv.begin(), pv.end(),
[&comp](const std::pair<size_t,RAIter>& a, const std::pair<size_t,RAIter>& b) -> bool
{ return comp(*a.second, *b.second) ; }) ;
indexes.resize(pv.size()) ;
std::transform(pv.begin(), pv.end(), indexes.begin(),
[](const std::pair<size_t,RAIter>& a) -> size_t { return a.first ; }) ;
}
使用方式与std::sort相同,除了还需要一个索引容器来接收排序后的索引。
注意:testing是原文中的示例,未作翻译处理。
int a[] = { 3, 1, 0, 4 } ;
std::vector<size_t> indexes ;
argsort(a, a + sizeof(a) / sizeof(a[0]), std::less<int>(), indexes) ;
for (size_t i : indexes) printf("%d\n", int(i)) ;
你应该得到 2 1 0 3。
对于没有C++0x支持的编译器,请将lambda表达式替换为类模板:
template <class RAIter, class Compare>
class PairComp {
public:
Compare comp ;
PairComp(Compare comp_) : comp(comp_) {}
bool operator() (const std::pair<size_t,RAIter>& a,
const std::pair<size_t,RAIter>& b) const { return comp(*a.second, *b.second) ; }
} ;
并将 std::sort 重写为
std::sort(pv.begin(), pv.end(), PairComp(comp)()) ;
template
class CompareIndicesByAnotherVectorValues
{
std::vector* _values;
public:
CompareIndicesByAnotherVectorValues(std::vector* values)
: _values(values) {}
public:
bool operator() (const int& a, const int& b) const
{
return (*_values)[a] > (*_values)[b];
}
};
该类用于根据另一个向量中的值比较索引,如果您无法使用lambda表达式,则可以使用它来完成同样的任务。 - Yoavfor (size_t i = 0; i != idx.size(); ++i) idx[i] = i;
,我更喜欢使用标准库函数std::iota(idx.begin(), idx.end(), 0);
。 - Wyck#include <numeric>
库中的iota()函数。 - kartikag01