对(双精度)实数向量进行排序并获得它们

发布于 2024-10-09 00:13:37 字数 416 浏览 4 评论 0原文

在 C++ 中,想要对一个冗长的 (2^20) 实数向量进行排序,显然 sort() 可以做到这一点。在使用 R 之前,我已经习惯了很好的 order() 函数,它产生导致排序向量的排列。

示例:

x = {24, 55, 22, 1}

然后排列

perm = {3, 2, 0, 1}

将原始 x 按升序映射到排序后的 x

我可能可以实现一些冒泡排序,它不仅对 x 进行排序,而且对向量 {0,1,2,...} 执行相同的转置并输出两者,但我相信有人一定想到了关于它,尤其是有效地完成了它。

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

暗地喜欢 2024-10-16 00:13:37

我想说最好的方法是创建一个整数 0..N 的向量,然后使用比较函数对该数组进行排序,该比较函数比较您试图找到排序排列的向量的相应元素。类似于:

#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;
}

这最大限度地减少了分配开销,因为我们不会创建任何大型临时对象来进行排序,然后提取最终的排列 - 返回的相同向量是用于排序的临时对象。

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.

北斗星光 2024-10-16 00:13:37

您可以使用 std::sort 对 {(24, 0), (55, 2), (22, 0), (1, 1)} 对列表进行排序。它不是特别漂亮,但我通常会这样做:

#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);
}

这是测试:

#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";
}

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";
}
愛上了 2024-10-16 00:13:37

编辑

比以前更好的方法,无需使用辅助向量:(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";
}

我正在使用 C++0x 中的 lambda,但它可以用简单的函子对象替换:

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));

带有 std::map 的旧解决方案的来源:ideone

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文