Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对自定义对象的向量进行排序_C++_Stl_Sorting - Fatal编程技术网

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

C++ 对自定义对象的向量进行排序,c++,stl,sorting,C++,Stl,Sorting,如何对包含自定义(即用户定义)对象的向量进行排序。 可能应该使用标准STL算法排序以及谓词(函数或函数对象),该谓词将对自定义对象中的一个字段(作为排序键)进行操作。 我在正确的轨道上吗?您可以使用functor作为std::sort的第三个参数,或者您可以在类中定义操作符,您可以重载“您在正确的轨道上。std::sort将使用操作符是,std::sort()和第三个参数(函数或对象)会更容易。例如: 一个使用 使用此方法意味着您可以简单地对向量进行如下排序: std::sort(vec.beg

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

我在正确的轨道上吗?

您可以使用functor作为
std::sort
的第三个参数,或者您可以在类中定义
操作符,您可以重载“您在正确的轨道上。
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());
//排序算法示例
#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
下面是使用

#包括
#包括
使用名称空间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
    仅包装一个基本值),则启用可能会导致重载
    运算符,以对可以使用sort()算法的向量进行排序

    sort(vec.begin(),vec.end(),less<int>());
    
    排序(vec.begin(),vec.end(),less());
    使用的第三个参数可以大于或小于,也可以使用任何函数或对象。但是,如果将第三个参数留空,则默认运算符为<

    // 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);
    
    //将函数用作comp
    排序(myvector.begin()+4,myvector.end(),myfunction);
    
    boolmyfunction(inti,intj){return(i您可以使用用户定义的比较器类

    class comparator
    {
        int x;
        bool operator()( const comparator &m,  const comparator &n )
        { 
           return m.x<n.x;
        }
     }
    
    类比较器
    {
    int x;
    布尔运算符()(常量比较器&m,常量比较器&n)
    { 
    返回m.x
    typedef结构Freqamp{
    双频;
    双安培;
    }频率放大器;
    布尔结构按频率(频率a、频率b)
    {
    返回a.freq

    如果compare为false,它将执行“swap”。

    我很好奇,在调用std::sort的各种方法之间,是否对性能有任何可测量的影响,因此我创建了这个简单的测试:

    $ 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;
    }
    
    以下是结果:

    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
    
    看起来除了传递函数指针之外的所有选项都非常相似,传递函数指针会导致+30%的惩罚


    看起来操作符
    #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;
    }
    

    错过了一个:提供一个成员函数运算符最好是使用
    运算符。您能解释一下为什么在结构中使用小于键的比较函数(在第一个示例中)内联吗?还有另一个问题/注意:如果希望使用多个排序方法(针对不同的属性)在一个类中,重载方法
    
    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