C++ 对自定义对象的向量进行排序

C++ 对自定义对象的向量进行排序,c++,stl,sorting,C++,Stl,Sorting,如何对包含自定义(即用户定义)对象的向量进行排序。 可能应该使用标准STL算法排序以及谓词(函数或函数对象),该谓词将对自定义对象中的一个字段(作为排序键)进行操作。 我走对了吗?你可以使用functor作为std::sort的第三个参数,或者你可以定义操作符你可以使用functor作为std::sort的第三个参数,或者你可以在你的类中定义操作符,你可以在你的类中重载“,你可以重载“你在正确的轨道上标准::排序将使用操作符您走在正确的轨道上std::sort将使用运算符Yes,std::sor

如何对包含自定义(即用户定义)对象的向量进行排序。
可能应该使用标准STL算法排序以及谓词(函数或函数对象),该谓词将对自定义对象中的一个字段(作为排序键)进行操作。

我走对了吗?

你可以使用functor作为
std::sort
的第三个参数,或者你可以定义
操作符你可以使用functor作为
std::sort
的第三个参数,或者你可以在你的类中定义
操作符,你可以在你的类中重载“,你可以重载“你在正确的轨道上<代码>标准::排序
将使用
操作符您走在正确的轨道上
std::sort
将使用
运算符Yes,
std::sort()
和第三个参数(函数或对象)将更容易。例如:

是的,
std::sort()
使用第三个参数(函数或对象)会更容易。例如: 一个使用

使用此方法意味着您可以简单地对向量进行如下排序:

std::sort(vec.begin(), vec.end());
Edit2:正如Kappa所建议的那样,您也可以通过重载
运算符并稍微更改sort调用来按降序对向量进行排序:

struct MyStruct
{
    int key;
    std::string stringValue;

    MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

    bool operator > (const MyStruct& str) const
    {
        return (key > str.key);
    }
};
您应该将sort称为:

std::sort(vec.begin(), vec.end(),greater<MyStruct>());
排序(vec.begin(),vec.end(),greater());
使用

使用此方法意味着您可以简单地对向量进行如下排序:

std::sort(vec.begin(), vec.end());
Edit2:正如Kappa所建议的那样,您也可以通过重载
运算符并稍微更改sort调用来按降序对向量进行排序:

struct MyStruct
{
    int key;
    std::string stringValue;

    MyStruct(int k, const std::string& s) : key(k), stringValue(s) {}

    bool operator > (const MyStruct& str) const
    {
        return (key > str.key);
    }
};
您应该将sort称为:

std::sort(vec.begin(), vec.end(),greater<MyStruct>());
排序(vec.begin(),vec.end(),greater());
//排序算法示例
#include//std::cout
#include//std::sort
#include//std::vector
使用名称空间std;
int main(){
字符myints[]={'F','C','E','G','A','H','B','D'};
向量myvector(myints,myints+8);/327112526805333
//使用默认比较(运算符
//排序算法示例
#include//std::cout
#include//std::sort
#include//std::vector
使用名称空间std;
int main(){
字符myints[]={'F','C','E','G','A','H','B','D'};
向量myvector(myints,myints+8);/327112526805333

//使用默认比较(操作符以实现覆盖率。我提出了一个使用默认比较的实现

C++11

#include <vector>
#include <algorithm>

using namespace std;

vector< MyStruct > values;

sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
{
   return lhs.key < rhs.key;
});
#包括
#包括
使用名称空间std;
向量值;
排序(values.begin()、values.end()、[](constmystruct&lhs、constmystruct&rhs)
{
返回lhs.key
C++14

#include <vector>
#include <algorithm>

using namespace std;

vector< MyStruct > values;

sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
{
   return lhs.key < rhs.key;
});
#包括
#包括
使用名称空间std;
向量值;
排序(values.begin()、values.end()、[](常量自动和lhs、常量自动和rhs)
{
返回lhs.key
为了覆盖率,我提出了一个使用的实现

C++11

#include <vector>
#include <algorithm>

using namespace std;

vector< MyStruct > values;

sort( values.begin( ), values.end( ), [ ]( const MyStruct& lhs, const MyStruct& rhs )
{
   return lhs.key < rhs.key;
});
#包括
#包括
使用名称空间std;
向量值;
排序(values.begin()、values.end()、[](constmystruct&lhs、constmystruct&rhs)
{
返回lhs.key
C++14

#include <vector>
#include <algorithm>

using namespace std;

vector< MyStruct > values;

sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
{
   return lhs.key < rhs.key;
});
#包括
#包括
使用名称空间std;
向量值;
排序(values.begin()、values.end()、[](常量自动和lhs、常量自动和rhs)
{
返回lhs.key
下面是使用

#包括
#包括
使用名称空间std;
结构MyStruct
{
int键;
std::字符串字符串值;
MyStruct(intk,conststd::string&s):key(k),stringValue(s){}
};
int main()
{
std::vectorvec;
向量推回(MyStruct(4,“测试”);
向量推回(MyStruct(3,“a”);
向量推回(MyStruct(2,“is”);
向量推回(MyStruct(1,“this”);
std::sort(vec.begin(),vec.end(),
[](常量MyStruct&struct1,常量MyStruct&struct2)
{
返回(struct1.key
下面是使用

#包括
#包括
使用名称空间std;
结构MyStruct
{
int键;
std::字符串字符串值;
MyStruct(intk,conststd::string&s):key(k),stringValue(s){}
};
int main()
{
std::vectorvec;
向量推回(MyStruct(4,“测试”);
向量推回(MyStruct(3,“a”);
向量推回(MyStruct(2,“is”);
向量推回(MyStruct(1,“this”);
std::sort(vec.begin(),vec.end(),
[](常量MyStruct&struct1,常量MyStruct&struct2)
{
返回(struct1.key
可以使用各种方法,尤其是使用标准库算法,如

  • ,
  • ,
由于大多数获得
X
元素相对顺序的技术已经发布,我将从使用各种方法的“为什么”和“何时”开始

“最佳”方法将取决于不同的因素:

  • X
    对象的范围进行排序是一项常见的任务还是一项罕见的任务(这些范围会在程序中的多个不同位置进行排序,还是由库用户进行排序)
  • 所需的排序是“自然”(预期)的还是有多种方式可以将类型与自身进行比较
  • 性能是一个问题还是
    X
    对象的排序范围应该万无一失

  • 如果
    X
    的排序范围是一项常见任务,并且预期会实现排序(即
    X
    仅包装一个基本值),则on可能会导致重载
    运算符对此类
    向量进行排序
    
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    vector< MyStruct > values;
    
    sort( values.begin( ), values.end( ), [ ]( const auto& lhs, const auto& rhs )
    {
       return lhs.key < rhs.key;
    });
    
    struct X {
      int i{}; 
      bool operator<(X const &r) const { return i < r.i; } 
    };
    // ...
    std::sort(vec_X.begin(), vec_X.end());
    
    struct Y {
      int j{}; 
    };
    bool operator<(Y const &l, Y const &r) { return l.j < r.j; }
    // ...
    std::sort(vec_Y.begin(), vec_Y.end());
    
    struct X {
      int i{};  
    };
    bool X_less(X const &l, X const &r) { return l.i < r.i; }
    // ...
    std::sort(vec_X.begin(), vec_X.end(), &X_less);
    
    struct X {
      int i{};  
      int j{};
    };
    struct less_X_i
    {
        bool operator()(X const &l, X const &r) const { return l.i < r.i; }
    };
    struct less_X_j
    {
        bool operator()(X const &l, X const &r) const { return l.j < r.j; }
    };
    // sort by i
    std::sort(vec_X.begin(), vec_X.end(), less_X_i{});
    // or sort by j
    std::sort(vec_X.begin(), vec_X.end(), less_X_j{});
    
    struct less_i
    { 
        template<class T, class U>
        bool operator()(T&& l, U&& r) const { return std::forward<T>(l).i < std::forward<U>(r).i; }
    };
    
    struct X {
      int i{}, j{};
    };
    std::sort(vec_X.begin(), vec_X.end(), [](X const &l, X const &r) { return l.i < r.i; });
    
    std::sort(a.begin(), a.end(), [](auto && l, auto && r) { return l.i < r.i; });
    
    #define COMPARATOR(code) [](auto && l, auto && r) -> bool { return code ; }
    
    // sort by i
    std::sort(v.begin(), v.end(), COMPARATOR(l.i < r.i));
    // sort by j
    std::sort(v.begin(), v.end(), COMPARATOR(l.j < r.j));
    
    sort(vec.begin(),vec.end(),less<int>());
    
    // using function as comp
    std::sort (myvector.begin()+4, myvector.end(), myfunction);
    bool myfunction (int i,int j) { return (i<j); }
    
    // using object as comp
    std::sort (myvector.begin(), myvector.end(), myobject);
    
    class comparator
    {
        int x;
        bool operator()( const comparator &m,  const comparator &n )
        { 
           return m.x<n.x;
        }
     }
    
    typedef struct Freqamp{
        double freq;
        double amp;
    }FREQAMP;
    
    bool struct_cmp_by_freq(FREQAMP a, FREQAMP b)
    {
        return a.freq < b.freq;
    }
    
    main()
    {
        vector <FREQAMP> temp;
        FREQAMP freqAMP;
    
        freqAMP.freq = 330;
        freqAMP.amp = 117.56;
        temp.push_back(freqAMP);
    
        freqAMP.freq = 450;
        freqAMP.amp = 99.56;
        temp.push_back(freqAMP);
    
        freqAMP.freq = 110;
        freqAMP.amp = 106.56;
        temp.push_back(freqAMP);
    
        sort(temp.begin(),temp.end(), struct_cmp_by_freq);
    }
    
    $ cat sort.cpp
    #include<algorithm>
    #include<iostream>
    #include<vector>
    #include<chrono>
    
    #define COMPILER_BARRIER() asm volatile("" ::: "memory");
    
    typedef unsigned long int ulint;
    
    using namespace std;
    
    struct S {
      int x;
      int y;
    };
    
    #define BODY { return s1.x*s2.y < s2.x*s1.y; }
    
    bool operator<( const S& s1, const S& s2 ) BODY
    bool Sgreater_func( const S& s1, const S& s2 ) BODY
    
    struct Sgreater {
      bool operator()( const S& s1, const S& s2 ) const BODY
    };
    
    void sort_by_operator(vector<S> & v){
      sort(v.begin(), v.end());
    }
    
    void sort_by_lambda(vector<S> & v){
      sort(v.begin(), v.end(), []( const S& s1, const S& s2 ) BODY );
    }
    
    void sort_by_functor(vector<S> &v){
      sort(v.begin(), v.end(), Sgreater());
    }
    
    void sort_by_function(vector<S> &v){
      sort(v.begin(), v.end(), &Sgreater_func);
    }
    
    const int N = 10000000;
    vector<S> random_vector;
    
    ulint run(void foo(vector<S> &v)){
      vector<S> tmp(random_vector);
      foo(tmp);
      ulint checksum = 0;
      for(int i=0;i<tmp.size();++i){
         checksum += i *tmp[i].x ^ tmp[i].y;
      }
      return checksum;
    }
    
    void measure(void foo(vector<S> & v)){
    
    ulint check_sum = 0;
    
      // warm up
      const int WARMUP_ROUNDS = 3;
      const int TEST_ROUNDS = 10;
    
      for(int t=WARMUP_ROUNDS;t--;){
        COMPILER_BARRIER();
        check_sum += run(foo);
        COMPILER_BARRIER();
      }
    
      for(int t=TEST_ROUNDS;t--;){
        COMPILER_BARRIER();
        auto start = std::chrono::high_resolution_clock::now();
        COMPILER_BARRIER();
        check_sum += run(foo);
        COMPILER_BARRIER();
        auto end = std::chrono::high_resolution_clock::now();
        COMPILER_BARRIER();
        auto duration_ns = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();
    
        cout << "Took " << duration_ns << "s to complete round" << endl;
      }
    
      cout << "Checksum: " << check_sum << endl;
    }
    
    #define M(x) \
      cout << "Measure " #x " on " << N << " items:" << endl;\
      measure(x);
    
    int main(){
      random_vector.reserve(N);
    
      for(int i=0;i<N;++i){
        random_vector.push_back(S{rand(), rand()});
      }
    
      M(sort_by_operator);
      M(sort_by_lambda);
      M(sort_by_functor);
      M(sort_by_function);
      return 0;
    }
    
    $ g++ -O2 -o sort sort.cpp && ./sort
    
    Measure sort_by_operator on 10000000 items:
    Took 0.994285s to complete round
    Took 0.990162s to complete round
    Took 0.992103s to complete round
    Took 0.989638s to complete round
    Took 0.98105s to complete round
    Took 0.991913s to complete round
    Took 0.992176s to complete round
    Took 0.981706s to complete round
    Took 0.99021s to complete round
    Took 0.988841s to complete round
    Checksum: 18446656212269526361
    Measure sort_by_lambda on 10000000 items:
    Took 0.974274s to complete round
    Took 0.97298s to complete round
    Took 0.964506s to complete round
    Took 0.96899s to complete round
    Took 0.965773s to complete round
    Took 0.96457s to complete round
    Took 0.974286s to complete round
    Took 0.975524s to complete round
    Took 0.966238s to complete round
    Took 0.964676s to complete round
    Checksum: 18446656212269526361
    Measure sort_by_functor on 10000000 items:
    Took 0.964359s to complete round
    Took 0.979619s to complete round
    Took 0.974027s to complete round
    Took 0.964671s to complete round
    Took 0.964764s to complete round
    Took 0.966491s to complete round
    Took 0.964706s to complete round
    Took 0.965115s to complete round
    Took 0.964352s to complete round
    Took 0.968954s to complete round
    Checksum: 18446656212269526361
    Measure sort_by_function on 10000000 items:
    Took 1.29942s to complete round
    Took 1.3029s to complete round
    Took 1.29931s to complete round
    Took 1.29946s to complete round
    Took 1.29837s to complete round
    Took 1.30132s to complete round
    Took 1.3023s to complete round
    Took 1.30997s to complete round
    Took 1.30819s to complete round
    Took 1.3003s to complete round
    Checksum: 18446656212269526361
    
    #include <iostream>
    #include <compare>
    #include <vector>
    #include <algorithm>
    
    struct MyInt
    {
        int value;
        MyInt(int val) : value(val) {}
        auto operator<=>(const MyInt& other) const = default;
    };
    
    
    int main()
    {
        MyInt Five(5);
        MyInt Two(2);
        MyInt Six(6);
        
        std::vector V{Five, Two, Six};
        std::sort(V.begin(), V.end());
        
        for (const auto& element : V)
            std::cout << element.value << std::endl;
    }
    
    2
    5
    6