运营商LT;严格的弱序

时间:2009-06-11 07:22:21

标签: c++ strict-weak-ordering

如何在n元组上定义operator<(例如在3元组上),以便它满足严格弱排序概念?我知道boost库具有正确定义operator<的元组类,但由于某些原因我无法使用它。

6 个答案:

答案 0 :(得分:51)

严格的弱排序

这是一个定义两个物体之间关系的数学术语 它的定义是:

  

如果f(x,y)和f(y,x)都为假,则两个对象x和y是等价的。请注意,对象始终(通过反射不变性)等同于自身。

就C ++而言,这意味着如果您有两个给定类型的对象,则在与运算符&lt;。

进行比较时,应返回以下值。
X    a;
X    b;

Condition:                  Test:     Result
a is equivalent to b:       a < b     false
a is equivalent to b        b < a     false

a is less than b            a < b     true
a is less than b            b < a     false

b is less than a            a < b     false
b is less than a            b < a     true

如何定义等效/减少完全取决于对象的类型。

正式定义:
Strict Weak ordering

计算机科学:
Strict Weak Ordering

与运营商的关系:
Comparator

答案 1 :(得分:38)

if (a1 < b1)
  return true;
if (b1 < a1)
  return false;

// a1==b1: continue with element 2
if (a2 < b2)
  return true;
if (b2 < a2)
  return false;

// a2 == b2: continue with element 3
if (a3 < b3)
  return true;
return false; // early out

这对元素的排序是a1最显着,a3最不重要。

这可以无限期地继续,你也可以例如将其应用于T的向量,迭代a [i]&lt;的比较。 a [i + 1] / a [i + 1]&lt;一个[i]中。该算法的另一种表达方式是“跳过时相等,然后比较”:

while (i<count-1 && !(a[i] < a[i+1]) && !(a[i+1] < a[i])
  ++i;
return i < count-1 && a[i] < a[i+1];

当然,如果比较费用昂贵,您可能希望缓存比较结果。


[edit]删除了错误的代码


[edit]如果只有operator<可用,我倾向于使用模式

if (a1 != b1)
  return a1 < b1;

if (a2 != b2)
  return a2 < b2;

...

答案 2 :(得分:27)

...对一个非常古老的问题的新答案,但现有的答案错过了C ++ 11中的简单解决方案......

C ++ 11解决方案

C ++ 11以后提供std::tuple<T...>,您可以使用它来存储数据。 tuple有匹配的operator<,最初比较最左边的元素,然后沿着元组工作,直到结果清晰。这适用于提供例如预期的strict weak orderingstd::setstd::map

如果您在其他变量中有数据(例如struct中的字段),您甚至可以使用std::tie()创建参考的元组,然后可以与另一个这样的元组相比。这样可以轻松地为用户定义的operator< / class类型中的特定成员数据字段编写struct

struct My_Struct
{
    int a_;
    double b_;
    std::string c_;
};

bool operator<(const My_Struct& lhs, const My_Struct& rhs)
{
    return std::tie(lhs.a_, lhs.b_, lhs.c_) < std::tie(rhs.a_, rhs.b_, rhs.c_);
}

答案 3 :(得分:6)

你可以简单地使用三元素向量,它们已经适当地使用了运算符&lt;() 定义。这样做的好处是它可以扩展到N元素而无需你做任何事情。

答案 4 :(得分:5)

基本流程应该是这样的:如果Kth元素不同,则返回哪个更小,否则转到下一个元素。下面的代码假设你有一个提升元组,否则你会使用get<N>(tuple)而没有问题开始。

if (lhs.first != rhs.first)
    return lhs.first < rhs.first;                
if (lhs.second != rhs.second)
    return lhs.second< rhs.second;
return lhs.third < rhs.third;

答案 5 :(得分:2)

即使你不能使用升级版本,你也应该能够破解代码。我从std :: pair中删除了这个 - 我认为3元组会相似。

return (_Left.first < _Right.first ||
        !(_Right.first < _Left.first) && _Left.second < _Right.second);

编辑:正如一些人指出的那样,如果您从标准库中窃取代码以在代码中使用,则应该重命名前面带有下划线的内容,因为这些名称是保留的。