当前位置:  开发笔记 > 编程语言 > 正文

如何使用std :: sort与结构向量和比较函数?

如何解决《如何使用std::sort与结构向量和比较函数?》经验,为你挑选了3个好方法。

感谢C中的解决方案,现在我想使用std :: sort和vector在C++中实现这一点:

typedef struct
{
  double x;
  double y;
  double alfa;
} pkt;

vector< pkt > wektor;使用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

什么是纠正?在这种情况下如何正确使用std :: sort?



1> Konrad Rudol..:

std::sort采用不同的比较函数qsort.该函数不是返回-1,0或1,而是返回一个bool值,该值指示第一个元素是否小于第二个元素.

你有两个可能性:operator <为你的对象实现; 在这种情况下,sort没有第三个参数的默认调用将起作用; 或者你可以重写你的上述功能来完成同样的事情.

请注意,您必须在参数中使用强类型.

此外,最好不要在这里使用功能.而是使用函数对象.这些受益于内联.

struct pkt_less {
    bool operator ()(pkt const& a, pkt const& b) const {
        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;
    }
};

// Usage:

sort(wektor.begin(), wektor.end(), pkt_less());


Dave,原因是仿函数可以内联,因为仿函数类型将告诉编译器在编译时调用哪个函数.使用函数指针,编译器只在运行时知道这一点,而且它不能内联.

2> Johannes Sch..:

在C++中,你可以使用类似的函数boost::bind很好地完成这项工作:

#include 
#include 

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

如果你需要多次这样做,你也可以通过创建一个接受成员指针并进行排序的函数对象来解决问题.您可以将它重用于任何类型的对象和成员.首先你如何使用它:

int main() {
    /* sorting a vector of pkt */
    std::vector 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));
}

这是make_cmp的代码.随意翻录(使用boost::preprocessor):

#include 
#include 

// 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              \
    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              \
    cmp##n                       \
        make_cmp(BOOST_PP_ENUM(n, PARAM_print, ~))                      \
    {                                                                   \
        return cmp##n(           \
            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



3> Christopher ..:

使用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;
});

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有