Sorting a vector of (double precision) reals and obtain their order

匿名 (未验证) 提交于 2019-12-03 03:08:02

问题:

in C++ would like to sort a lengthy (2^20) vector of reals, obviously sort() does the trick. Having used R before I was used to the nice order() function which yields the permutation that leads to the sorted vector. Probably someone has done this in C++, maybe it's just my weak google-Fu that prevents me from finding it. And yeah, obivously my C++ newbness could stop me from spotting something straightforward.

Example:

x = {24, 55, 22, 1}

then the permutation

perm = {3, 2, 0, 1}

maps the original x to the sorted x in ascending order.

I can probably implement some bubble sort which does not only sort x but performs the same transpositions on the vector {0,1,2,...} and outputs both, but I believe someone must have thought about it and especially have done it efficiently.

Thank you very much, Philipp

回答1:

Edit

Better than before approach without using helper vectors: (source on ideone):

#include <vector> #include <algorithm> #include <iostream>  template<class Vals> void sortingPermutation(const Vals& values, std::vector<int>& v){   int size = values.size();    v.clear(); v.reserve(size);   for(int i=0; i < size; ++i)     v.push_back(i);    std::sort(v.begin(), v.end(), [&values](int a, int b) -> bool {      return values[a] < values[b];   }); }  int main() {     std::vector<double> values;     values.push_back(24);     values.push_back(55);     values.push_back(22);     values.push_back(1);      std::vector<int> permutation;     sortingPermutation(values, permutation);      typedef std::vector<int>::const_iterator I;     for (I p = permutation.begin(); p != permutation.end(); ++p)         std::cout << *p << " ";     std::cout << "\n"; }

I am using lambda from C++0x, but it can be replaced with simple functor object:

template<class T> struct CmpPairs{   CmpPairs(const std::vector<T> &v): v_(v) {}   std::vector<T> v_;   bool operator()(int a, int b){ return v_[a] < v_[b]; } };  template<class T> CmpPairs<T> CreateCmpPairs(const std::vector<T> & v) { return CmpPairs<T>(v); } //in sortingPermutation: std::sort(v.begin(), v.end(), CreateCmpPairs(values));

Source of old solution with std::map: ideone



回答2:

I would say the best way would be to create a vector of ints 0..N and then sort that array with a comparison function that compares the corresponding elements of the vector you're trying to find the sorted permutation of. Something like:

#include <vector> #include <algorithm>  template<class T> class sorter {     const std::vector<T> &values; public:     sorter(const std::vector<T> &v) : values(v) {}     bool operator()(int a, int b) { return values[a] < values[b]; } };  template<class T> std::vector<int> order(const std::vector<T> &values) {     std::vector<int> rv(values.size());     int idx = 0;     for (std::vector<int>::iterator i = rv.begin(); i != rv.end(); i++)         *i = idx++;     std::sort(rv.begin(), rv.end(), sorter<T>(values));     return rv; }

This minimizes the allocation overhead, as we don't create any large temporary object that we sort and then extract the final permution -- the same vector that is being returned is the temp for sorting.



回答3:

You can use std::sort to sort the list of pairs {(24, 0), (55, 2), (22, 0), (1, 1)}. It isn't particularly pretty, but I usually do something like this:

#include <vector> #include <algorithm> #include <utility>  typedef std::pair<double, int> Pair;  struct CmpPair {     bool operator()(const Pair& a, const Pair& b)     { return a.first < b.first; } };  void sortingPermutation(     const std::vector<double>& values,     std::vector<int>& permutation) {     std::vector<Pair> pairs;     for (int i = 0; i < (int)values.size(); i++)         pairs.push_back(Pair(values[i], i));      std::sort(pairs.begin(), pairs.end(), CmpPair());      typedef std::vector<Pair>::const_iterator I;     for (I p = pairs.begin(); p != pairs.end(); ++p)         permutation.push_back(p->second); }

Here is the test:

#include <iostream>  int main() {     std::vector<double> values;     values.push_back(24);     values.push_back(55);     values.push_back(22);     values.push_back(1);      std::vector<int> permutation;     sortingPermutation(values, permutation);      typedef std::vector<int>::const_iterator I;     for (I p = permutation.begin(); p != permutation.end(); ++p)         std::cout << *p << " ";     std::cout << "\n"; }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!