Do you have some efficient routine for returning array with indices for sorted elements in a array? I think that some convenient way exists using stl vector
. Do you have already implemented an efficient algo without stl, or do you have a reference to pseudo code or C++ code?
Create an array of type int with the same size containing the indices. When sorting the float array simply mirror any swap operation on your int array. Use a struct with an index field, write the index of each element before sorting, and that will retain the original position in the array.
A simple solution would be to use efficient sorting algorithms like Merge Sort, Quicksort, Heapsort, etc., that can solve this problem in O(n. log(n)) time, but those will not take advantage of the fact that there are many duplicated values in the array. A better approach is to use a counting sort.
Given two integer arrays of same size, “arr[]” and “index[]”, reorder elements in “arr[]” according to given index array. It is not allowed to given array arr's length.
As of September 2020, it appears that libc++ std::sort happens to be stable for all ranges of size less than 31, and libstdc++ std::sort happens to be stable for all ranges of size less than 17.
Using C++11, the following should work just fine:
template <typename T>
std::vector<size_t> ordered(std::vector<T> const& values) {
std::vector<size_t> indices(values.size());
std::iota(begin(indices), end(indices), static_cast<size_t>(0));
std::sort(
begin(indices), end(indices),
[&](size_t a, size_t b) { return values[a] < values[b]; }
);
return indices;
}
You could try something like this:
template<typename C>
class index_sorter {
public:
compare(C const& c) : c(c) {}
bool operator()(std::size_t const& lhs, std::size_t const& rhs) const {
return c[lhs] < c[rhs];
}
private:
C const& c;
};
std::sort(index_vector.begin(), index_vector.end(), index_sorter(vector));
Adding to @Konrad answer:
If for some reason you are not able to use C++11, then you can use boost::phoenix
to simulate it like
#include <vector>
#include <algorithm>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
template <typename T>
std::vector<size_t> ordered(std::vector<T> const& values)
{
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
std::vector<size_t> indices(values.size());
int i = 0;
std::transform(values.begin(), values.end(), indices.begin(), ref(i)++);
std::sort(indices.begin(), indices.end(), ref(values)[arg1] < ref(values)[arg2]);
return indices;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With