如何在C ++中有效地排序四重结构?

时间:2013-06-13 06:40:01

标签: c++ c++11 stl tuples lexicographic

我有一个包含成员x,y,z和w的结构。我如何有效排序 先用x,然后是y,用z,最后是用C ++中的w?

4 个答案:

答案 0 :(得分:9)

如果要实现字典排序,那么最简单的方法是使用std::tie来实现小于或大于比较的运算符或仿函数,然后在集合上使用std::sort你的结构。

struct Foo
{
  T x, y, z, w;
};

....    
#include <tuple> // for std::tie

bool operator<(const Foo& lhs, const Foo& rhs)
{
  // assumes there is a bool operator< for T
  return std::tie(lhs.x, lhs.y, lhs.z, lhs.w) < std::tie(rhs.x, rhs.y, rhs.z, rhs.w);
}

....

#include <algorithm> // for std::sort

std::vector<Foo> v = ....;
std::sort(v.begin(), v.end());

如果Foo没有自然排序,最好定义比较仿函数而不是实现比较运算符。然后,您可以将这些传递给sort:

bool cmp_1(const Foo& lhs, const Foo& rhs)
{
  return std::tie(lhs.x, lhs.y, lhs.z, lhs.w) < std::tie(rhs.x, rhs.y, rhs.z, rhs.w);
}

std::sort(v.begin(), v.end(), cmp_1);

如果您没有C ++ 11 tuple支持,则可以使用std::tr1::tie(使用标头<tr1/tuple>)或使用boost.tuple library来实现此功能}}

答案 1 :(得分:6)

您可以使用std::tuple将结构转换为std::tie,并使用字典比较std::tuple::operator<。这是使用lambda到std::sort

的示例
#include <algorithm>
#include <tuple> 
#include <vector>

struct S 
{
   // x, y, z, w can be 4 different types!
   int x, y, z, w;
};

std::vector<S> v;

std::sort(std::begin(v), std::end(v), [](S const& L, S const& R) {
    return std::tie(L.x, L.y, L.z, L.w) < std::tie(R.x, R.y, R.z, R.w);
});

此示例为std:sort提供了一个即时比较运算符。如果您总是希望使用字典比较,则可以编写由bool operator<(S const&, S const&)std::sortstd::set等有序关联容器自动选择的非成员std::map

关于效率,来自online reference

  

所有比较运算符都是短路的;他们不访问元组   超出确定结果所必需的元素   比较。

如果您有C ++ 11环境,请选择此处给出的手写解决方案std::tie。它们更容易出错且可读性更低。

答案 2 :(得分:2)

如果您推送自己的比较运算符,则可以自由地将对象放入std::map或调用std::sort。此实现设计简单,因此您可以根据需要轻松验证和修改它。通过仅使用operator<来比较x,y,z和w,如果这些变量不是已经可比较的话,它可以最小化您可能需要实现的运算符的数量(例如,如果它们是您自己的结构而不是整数,则加倍,std :: strings等。)。

bool operator<(const Q& lhs, const Q& rhs)
{
    if (lhs.x < rhs.x) return true;
    if (rhs.x < lhs.x) return false;
    if (lhs.y < rhs.y) return true;
    if (rhs.y < lhs.y) return false;
    if (lhs.z < rhs.z) return true;
    if (rhs.z < lhs.z) return false;
    if (lhs.w < rhs.w) return true;
    return false;
}

有时,类型将定义一个返回-1,0或1的比较函数,以指示小于,等于或大于两者,作为支持<<=的实现的方式,==!=>=>,还因为有时会<!=>会重复很多工作(考虑比较只有最后一个字符不同的长文本字符串)。如果x,y,z和w恰好属于这种类型且具有更高性能的比较功能,则可以通过以下方式提高整体性能:

bool operator<(const Q& lhs, const Q& rhs)
{
    int c;
    return (c = lhs.x.compare(rhs.x) ? c :
           (c = lhs.y.compare(rhs.y) ? c :
           (c = lhs.z.compare(rhs.z) ? c :
           lhs.w < rhs.w;
}

答案 3 :(得分:2)

此解决方案每个元素最多进行4次比较 - 比较并且不需要构建其他对象:

// using function as comp
std::sort (quadrupleVec.begin(), quadrupleVec.end(), [](const Quadruple& a, const Quadruple& b)
{
    if (a.x != b.x) 
        return a.x < b.x;

    if (a.y != b.y)
        return a.y < b.y;

    if (a.z != b.z)
        return a.z < b.z;

    return a.w < b.w;
});