Using C++, and hopefully the standard library, I want to sort a sequence of samples in ascending order, but I also want to remember the original indexes of the new samples.<
Suppose Given vector is
A=[2,4,3]
Create a new vector
V=[0,1,2] // indicating positions
Sort V and while sorting instead of comparing elements of V , compare corresponding elements of A
//Assume A is a given vector with N elements
vector<int> V(N);
int x=0;
std::iota(V.begin(),V.end(),x++); //Initializing
sort( V.begin(),V.end(), [&](int i,int j){return A[i]<A[j];} );
I wrote generic version of index sort.
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 ; }) ;
}
Usage is the same as that of std::sort except for an index container to receive sorted indexes. 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)) ;
you should get 2 1 0 3. for the compilers without c++0x support, replace the lamba expression as a class template:
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) ; }
} ;
and rewrite std::sort as
std::sort(pv.begin(), pv.end(), PairComp(comp)()) ;
vector<pair<int,int> >a;
for (i = 0 ;i < n ; i++) {
// filling the original array
cin >> k;
a.push_back (make_pair (k,i)); // k = value, i = original index
}
sort (a.begin(),a.end());
for (i = 0 ; i < n ; i++){
cout << a[i].first << " " << a[i].second << "\n";
}
Now a
contains both both our values and their respective indices in the sorted.
a[i].first = value
at i
'th.
a[i].second = idx
in initial array.