如何在c++中有效地对四重结构体进行排序

How do I sort efficiently a quadruple structs in C++?

本文关键字:四重 结构体 排序 c++ 有效地      更新时间:2023-10-16

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

如果您想实现字典排序,那么最简单的方法是使用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::tie从boost实现这一点。元组库。

您可以使用std::tie将结构体转换为std::tuple,并使用字典比较std::tuple::operator<。下面是对std::sort

使用lambda的示例
#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::sort或有序关联容器(如std::setstd::map)自动选择。

关于效率,来自在线参考:

所有比较操作符都是短路的;它们不访问元组元素超出了确定结果所必需的范围比较。

如果您有c++ 11环境,请选择std::tie而不是这里给出的手写解决方案。它们更容易出错,可读性更差。

此解决方案每个元素最多有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;
});

如果您滚动自己的比较操作符,那么您可以自由地将对象扔到std::map s或调用std::sort。此实现设计得很简单,因此您可以在需要时轻松验证和修改它。通过只使用operator<来比较x, y, z和w,如果这些变量不具有可比性(例如,如果它们是你自己的结构体而不是int, double, std::string等),它可以最大限度地减少你可能需要实现的操作符的数量。

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