sorting自定义对象的vector
如何sorting包含自定义(即用户定义)对象的vector。
应该使用标准的STLalgorithm和一个谓词(一个函数或一个函数对象),它们将在自定义对象中的一个字段上操作(作为sorting的关键)。
我在正确的轨道上?
一个简单的例子,使用std::sort
struct MyStruct { int key; std::string stringValue; MyStruct(int k, const std::string& s) : key(k), stringValue(s) {} }; struct less_than_key { inline bool operator() (const MyStruct& struct1, const MyStruct& struct2) { return (struct1.key < struct2.key); } }; std::vector < MyStruct > vec; vec.push_back(MyStruct(4, "test")); vec.push_back(MyStruct(3, "a")); vec.push_back(MyStruct(2, "is")); vec.push_back(MyStruct(1, "this")); std::sort(vec.begin(), vec.end(), less_than_key());
编辑:正如Kirill V. Lyadvinsky所指出的那样,不是提供sorting谓词,而是可以实现operator<
for MyStruct
:
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); } };
使用这个方法意味着你可以简单地按如下方式对向量进行sorting
std::sort(vec.begin(), vec.end());
Edit2:由于Kappabuild议你也可以通过override>操作符降序排列向量,并改变sorting调用一下:
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); } };
你应该把它称为:
std::sort(vec.begin(), vec.end(),greater<MyStruct>());
为了覆盖的利益。 我提出了一个使用lambdaexpression式的实现。
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; });
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; });
你可以使用functor作为std::sort
第三个参数,或者你可以在你的类中定义operator<
。
struct X { int x; bool operator<( const X& val ) const { return x < val.x; } }; struct Xgreater { bool operator()( const X& lx, const X& rx ) const { return lx.x < rx.x; } }; int main () { std::vector<X> my_vec; // use X::operator< by default std::sort( my_vec.begin(), my_vec.end() ); // use functor std::sort( my_vec.begin(), my_vec.end(), Xgreater() ); }
你在正确的轨道上。 std::sort
默认使用operator<
作为比较函数。 所以为了sorting你的对象,你必须重载bool operator<( const T&, const T& )
或者提供一个函数来进行比较,就像这样:
struct C { int i; static bool before( const C& c1, const C& c2 ) { return c1.i < c2.i; } }; bool operator<( const C& c1, const C& c2 ) { return c1.i > c2.i; } std::vector<C> values; std::sort( values.begin(), values.end() ); // uses operator< std::sort( values.begin(), values.end(), C::before );
使用函子的好处是你可以使用一个函数来访问类的私有成员。
对typesX
的自定义对象的这种vector
或任何其他适用(可变input迭代器)范围进行sorting可以使用各种方法来实现,特别是包括使用标准库algorithm
-
sort
, -
stable_sort
, -
partial_sort
或 -
partial_sort_copy
。
由于大多数获得X
元素的相对顺序的技术已经发布,我将从“为什么”和“何时”使用各种方法开始。
“最好”的做法将取决于不同的因素:
- 是sorting
X
对象的范围一个共同的或稀有的任务(这样的范围sorting在程序或库用户的多个不同的地方)? - 所需的sorting“自然”(预期)还是有多种方式可以比较自己的types?
- 性能是一个问题还是应该sorting的
X
对象的范围是万无一失的?
如果X
sorting范围是一个常见的任务,并且实现的sorting是预期的(即X
只是包装一个基本值),那么可能会超载operator<
因为它允许sorting没有任何模糊(如正确传递适当的比较器)并一再产生预期的结果。
如果sorting是一个常见的任务,或者可能在不同的上下文中需要,但是有多个标准可以用来sortingX
对象,我会去找Functors(自定义类的重载operator()
函数)或函数指针一个用于词法sorting的函数/函数,另一个用于自然sorting)。
如果X
types的sorting范围在其他上下文中不常见或不太可能,我倾向于使用lambdaexpression式,而不是使用更多的函数或types混淆任何名称空间。
如果sorting不是以某种方式“清晰”或“自然”的话,情况尤其如此。 您可以很容易地在查看应用在原地的lambdaexpression式时查看后面的逻辑,而operator<
是一见钟情的,您必须查看定义,才能知道将应用什么sorting逻辑。
但请注意,单个operator<
定义是单点故障,而多个兰博是多个故障点,需要更多的注意。
如果operator<
的定义在sorting完成/sorting模板被编译时不可用,那么编译器可能会在比较对象时被迫进行函数调用,而不是内联sorting逻辑,这可能是一个严重的缺陷(在至less当不应用链接时间优化/代码生成时)。
如何使用标准库sortingalgorithm来实现class X
可比性
让std::vector<X> vec_X;
和std::vector<Y> vec_Y;
1.重载T::operator<(T)
或operator<(T, T)
并使用不需要比较函数的标准库模板。
重载成员operator<
:
struct X { int i{}; bool operator<(X const &r) const { return i < ri; } }; // ... std::sort(vec_X.begin(), vec_X.end());
或免费operator<
:
struct Y { int j{}; }; bool operator<(Y const &l, Y const &r) { return lj < rj; } // ... std::sort(vec_Y.begin(), vec_Y.end());
2.使用具有自定义比较函数的函数指针作为sorting函数参数。
struct X { int i{}; }; bool X_less(X const &l, X const &r) { return li < ri; } // ... std::sort(vec_X.begin(), vec_X.end(), &X_less);
3.为可以作为比较函数传递的自定义types创build一个bool operator()(T, T)
重载。
struct X { int i{}; int j{}; }; struct less_X_i { bool operator()(X const &l, X const &r) const { return li < ri; } }; struct less_X_j { bool operator()(X const &l, X const &r) const { return lj < rj; } }; // 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{});
这些函数对象定义可以用C ++ 11和模板写得更通用:
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; } };
它可以用来sorting任何types的成员i
支持<
。
4.将anonymus闭包(lambda)作为比较parameter passing给sorting函数。
struct X { int i{}, j{}; }; std::sort(vec_X.begin(), vec_X.end(), [](X const &l, X const &r) { return li < ri; });
C ++ 14支持更通用的lambdaexpression式:
std::sort(a.begin(), a.end(), [](auto && l, auto && r) { return li < ri; });
可以用macros包装
#define COMPARATOR(code) [](auto && l, auto && r) -> bool { return code ; }
使普通的比较器创build非常stream畅:
// sort by i std::sort(v.begin(), v.end(), COMPARATOR(li < ri)); // sort by j std::sort(v.begin(), v.end(), COMPARATOR(lj < rj));
是的,与第三个参数(函数或对象)的std::sort()
)会更容易。 一个例子: http : //www.cplusplus.com/reference/algorithm/sort/
在你的课堂上,你可能会重载“<”运算符。
class MyClass { bool operator <(const MyClass& rhs) { return this->key < rhs.key; } }
以下是使用lambdas的代码
#include "stdafx.h" #include <vector> #include <algorithm> using namespace std; struct MyStruct { int key; std::string stringValue; MyStruct(int k, const std::string& s) : key(k), stringValue(s) {} }; int main() { std::vector < MyStruct > vec; vec.push_back(MyStruct(4, "test")); vec.push_back(MyStruct(3, "a")); vec.push_back(MyStruct(2, "is")); vec.push_back(MyStruct(1, "this")); std::sort(vec.begin(), vec.end(), [] (const MyStruct& struct1, const MyStruct& struct2) { return (struct1.key < struct2.key); } ); return 0; }
您可以使用用户定义的比较器类。
class comparator { int x; bool operator()( const comparator &m, const comparator &n ) { return mx<nx; } }
// sort algorithm example #include <iostream> // std::cout #include <algorithm> // std::sort #include <vector> // std::vector using namespace std; int main () { char myints[] = {'F','C','E','G','A','H','B','D'}; vector<char> myvector (myints, myints+8); // 32 71 12 45 26 80 53 33 // using default comparison (operator <): sort (myvector.begin(), myvector.end()); //(12 32 45 71)26 80 53 33 // print out content: cout << "myvector contains:"; for (int i=0; i!=8; i++) cout << ' ' <<myvector[i]; cout << '\n'; system("PAUSE"); return 0; }
为了sorting一个向量,你可以使用sort()algorithm。
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);
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); }
如果比较是错误的,它会做“交换”。