Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ sort keeping track of indices [duplicate]

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?

like image 334
kiriloff Avatar asked May 14 '12 09:05

kiriloff


People also ask

How to sort an array and keep track of the index in C?

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.

Which sorting algorithm is best for duplicates?

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.

How to reorder array index?

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.

Is std :: sort stable?

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.


3 Answers

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;
}
like image 142
Konrad Rudolph Avatar answered Oct 11 '22 02:10

Konrad Rudolph


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));
like image 7
Pubby Avatar answered Oct 11 '22 02:10

Pubby


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;
    }
like image 4
Kostya Avatar answered Oct 11 '22 04:10

Kostya