根据cppreference:
在不等式比较(<,>)中,比较第一个元素 首先,只有当不平等比较不适合他们时, 第二个要素进行了比较。
翻译成这样的东西:
return ((a.first < b.first) || (!(b.first < a.first) && (a.second < b.second)));
我的问题是,为什么它如此不直观? 背后的原因是什么?是否存在这种推理可以得出正确答案的例子?
我认为实施只会是:
return a.first < b.first && a.second < b.second
答案 0 :(得分:12)
这种比较称为 lexicographical ordering ,是将两种不同排序合并为一种的更自然的方法之一。
C ++中请求的排序称为 strict weak orderings 。这意味着以下情况应该成立:
这些属性是您需要的,以确保您可以获取对象列表并将它们按升序排序。这意味着您可以对其使用std::sort
,或将其存储在std::set
。
你可以用一些数学证明,如果你有两个不同的严格弱排序,那么你通过将它们组合为std::pair
得到的词典排序也是一个严格的弱排序。词典排序是你可以将严格的弱顺序结合起来制定新的严格弱序的少数方法之一。
但是,您建议的顺序是不严格的弱排序,并会导致某些假设中断。特别是,考虑对(0,5),(3,3)和(1,6)。然后(0,5)与(3,3)无法比较,并且(3,3)与(1,6)无法比较。但是,我们确实有(0,5)&lt; (1,6),它打破了等价传递的规则。因此,许多假定等价是可传递的排序算法(包括大多数主要排序算法)将无法在您的范围内正常工作,这意味着std::sort
可能表现不正确。这也意味着你也无法将它们存储在std::set
中,因为std::set
以某种排序顺序(通常是平衡的二叉搜索树)存储所有内容,你可能会得到完全错误的结果
希望这有帮助!
答案 1 :(得分:6)
如果a.first
小于b.first
,则该对已经不足了。没有理由比较第二部分。对于第一部分,第一部分隐含地排序,就像名字首先按其第一个字母排序一样。 “Apple”出现在“Zebra”之前,因为“A”出现在“Z”之前,我们根本不将“p”与“e”进行比较。
所以,如果a.first < b.first
,我们就完成了。但是,如果没有,我们就没有完成。另一种方式a
可能小于b
。如果b.first < a.first
不是这种情况,那就是a.second < b.second
。
类比将是“Zebra”和“Zyman”。 “Z”不小于“Z”,但“e”小于“y”,所以第一次小于第二次。
您有时会看到它以这种方式编码:
bool operator<(const foo& a, const foo& b) {
if (a.first < b.first) return true;
if (a.first > b.first) return false;
return (a.second < b.second);
}
我发现直觉上这更容易理解,但逻辑是一样的:
答案 2 :(得分:4)
直觉是旁观者的眼睛。我实际上发现它非常直观。
它与您比较其他序列时的行为一样。例如,你会说字符串"az"
出现在"ba"
之前,对吧?但你没有'a' < 'b' && 'z' < 'a'
!同样的推理适用于成对。它不仅更直观,而且还保持了这种关系的所有理想属性。