C++ 如何将std::sort与结构向量一起使用并比较函数?
谢谢你的邀请, 现在我想用C++实现这个:使用STD::排序和向量:C++ 如何将std::sort与结构向量一起使用并比较函数?,c++,sorting,stl,vector,C++,Sorting,Stl,Vector,谢谢你的邀请, 现在我想用C++实现这个:使用STD::排序和向量: typedef struct { double x; double y; double alfa; } pkt; vectorwektor使用push_back()填充;比较功能: int porownaj(const void *p_a, const void *p_b) { pkt *pkt_a = (pkt *) p_a; pkt *pkt_b = (pkt *) p_b; if (pkt_a
typedef struct
{
double x;
double y;
double alfa;
} pkt;
vectorwektor代码>使用push_back()填充;比较功能:
int porownaj(const void *p_a, const void *p_b)
{
pkt *pkt_a = (pkt *) p_a;
pkt *pkt_b = (pkt *) p_b;
if (pkt_a->alfa > pkt_b->alfa) return 1;
if (pkt_a->alfa < pkt_b->alfa) return -1;
if (pkt_a->x > pkt_b->x) return 1;
if (pkt_a->x < pkt_b->x) return -1;
return 0;
}
sort(wektor.begin(), wektor.end(), porownaj); // this makes loads of errors on compile time
int porownaj(const void*p_a,const void*p_b)
{
pkt*pkt_a=(pkt*)p_a;
pkt*pkt_b=(pkt*)p_b;
if(pkt_a->alfa>pkt_b->alfa)返回1;
if(pkt_a->alfaalfa)返回-1;
if(pkt_a->x>pkt_b->x)返回1;
if(pkt_a->xx)返回-1;
返回0;
}
排序(wektor.begin()、wektor.end()、porownaj);//这会在编译时产生大量错误
纠正什么?在这种情况下如何正确使用std::sort?std::sort
采用了与qsort
中使用的不同的比较函数。此函数不返回–1、0或1,而是返回一个bool
值,指示第一个元素是否小于第二个元素
您有两个可能:在C++中实现<代码>运算符> p>,可以使用像<代码> Boo::BooN/CODEM >的函数符,这项工作做得很好:
#include <vector>
#include <algorithm>
struct pkt {
double x;
double y;
double alfa;
pkt(double x, double y, double alfa)
:x(x), y(y), alfa(alfa) { }
};
int main() {
std::vector<pkt> p;
p.push_back(pkt(10., 0., 20.));
p.push_back(pkt(10, 0., 30.));
p.push_back(pkt(5., 0., 40.));
std::sort(p.begin(), p.end(),
boost::bind(&pkt::alfa, _1) < boost::bind(&pkt::alfa, _2) ||
boost::bind(&pkt::alfa, _1) == boost::bind(&pkt::alfa, _2) &&
boost::bind(&pkt::x, _1) < boost::bind(&pkt::x, _2));
}
对于C++0x和lambdas Konrad,其解决方案如下所示:
sort(wektor.begin(), wektor.end(), [](pkt const& a, pkt const& b)
{
if (a.alfa < b.alfa) return true;
if (a.alfa > b.alfa) return false;
if (a.x < b.x) return true;
if (a.x > b.x) return false;
return false;
});
sort(wektor.begin()、wektor.end()、[](pkt常量&a、pkt常量&b)
{
如果(a.alfab.alfa)返回false;
如果(a.xb.x)返回false;
返回false;
});
您甚至不需要使用函子。为什么不直接使用普通函数,代码行更少?Dave,原因是函子可以内联,因为函子类型会告诉编译器在编译时调用哪个函数。使用函数指针,编译器只在运行时知道这一点,而不能内联。@onebyone.livejournal.com:不正确。函数指针不能内联。不允许编译器进行该优化。(虽然指针是函子)。@Konrad Rudolph:您的方法与原始方法不同:最终返回值不应比较y,而应逐个返回false。请参阅:bool(*)(T const&,T const&)可能是编译器看到的类型。有无限多个函数具有这种类型,它们都做不同的事情。但是如果你有U,U是一个类类型重载op(),那么只有一个重载解析可以解决。
int main() {
/* sorting a vector of pkt */
std::vector<pkt> p;
p.push_back(pkt(10., 0., 20.));
p.push_back(pkt(5., 0., 40.));
std::sort(p.begin(), p.end(), make_cmp(&pkt::x, &pkt::y));
}
#include <boost/preprocessor/repetition.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
// tweak this to increase the maximal field count
#define CMP_MAX 10
#define TYPEDEF_print(z, n, unused) typedef M##n T::* m##n##_type;
#define MEMBER_print(z, n, unused) m##n##_type m##n;
#define CTORPARAMS_print(z, n, unused) m##n##_type m##n
#define CTORINIT_print(z, n, unused) m##n(m##n)
#define CMPIF_print(z, n, unused) \
if ((t0.*m##n) < (t1.*m##n)) return true; \
if ((t0.*m##n) > (t1.*m##n)) return false; \
#define PARAM_print(z, n, unused) M##n T::* m##n
#define CMP_functor(z, n, unused) \
template <typename T \
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename M)> \
struct cmp##n { \
BOOST_PP_REPEAT(n, TYPEDEF_print, ~) \
BOOST_PP_REPEAT(n, MEMBER_print, ~) \
cmp##n(BOOST_PP_ENUM(n, CTORPARAMS_print, ~)) \
BOOST_PP_IF(n, :, BOOST_PP_EMPTY()) \
BOOST_PP_ENUM(n, CTORINIT_print, ~) { } \
\
bool operator()(T const& t0, T const& t1) const { \
BOOST_PP_REPEAT(n, CMPIF_print, ~) \
return false; \
} \
}; \
\
template<typename T \
BOOST_PP_ENUM_TRAILING_PARAMS(n, typename M)> \
cmp##n<T BOOST_PP_ENUM_TRAILING_PARAMS(n, M)> \
make_cmp(BOOST_PP_ENUM(n, PARAM_print, ~)) \
{ \
return cmp##n<T BOOST_PP_ENUM_TRAILING_PARAMS(n, M)>( \
BOOST_PP_ENUM_PARAMS(n, m)); \
}
BOOST_PP_REPEAT(CMP_MAX, CMP_functor, ~)
#undef TYPEDEF_print
#undef MEMBER_print
#undef CTORPARAMS_print
#undef CTORINIT_print
#undef CMPIF_print
#undef PARAM_print
#undef CMP_functor
sort(wektor.begin(), wektor.end(), [](pkt const& a, pkt const& b)
{
if (a.alfa < b.alfa) return true;
if (a.alfa > b.alfa) return false;
if (a.x < b.x) return true;
if (a.x > b.x) return false;
return false;
});