【问题标题】:Global inequality comparisons for pair<> in C++ standardC++ 标准中 pair<> 的全局不等式比较
【发布时间】:2012-01-19 22:59:06
【问题描述】:
根据cppreference:
在不等式比较()中,比较第一个元素
首先,并且只有当不等式比较对他们不成立时,
比较第二个元素。
翻译成这样的:
return ((a.first < b.first) || (!(b.first < a.first) && (a.second < b.second)));
我的问题是,为什么这么不直观? 背后的原因是什么?有没有这样的推理导致正确答案的例子?
我认为实现只是:
return a.first < b.first && a.second < b.second
【问题讨论】:
标签:
c++
math
comparison
standards
std-pair
【解决方案1】:
这种比较称为 lexicographical ordering,是一种将两种不同的排序合并为一个的更自然的方法。
在 C++ 中请求的排序称为 strict weak orderings。这意味着以下应该是正确的:
-
非自反性: x
-
传递性:如果 x
-
反对称:如果 x
-
等价传递性:如果x和y不可比,y和z不可比,则x和z不可比。
这些属性是您需要的,以确保您可以获取对象列表并将它们按升序排列。这意味着您可以在它们上使用std::sort,或者将它们存储在std::set 中。
您可以通过一些数学证明,如果您有两个不同的严格弱排序,那么通过将它们组合为std::pair 得到的字典顺序也是严格弱排序。字典顺序是您可以组合严格弱排序以生成新的严格弱排序的少数几种方法之一。
但是,您建议的排序不是严格的弱排序,会导致某些假设被打破。特别是,考虑对 (0, 5)、(3, 3) 和 (1, 6)。则 (0, 5) 与 (3, 3) 不可比, (3, 3) 与 (1, 6) 不可比。但是,我们确实有 (0, 5) 等价传递性的规则。因此,许多假设等价是可传递的排序算法(包括大多数主要的排序算法)将无法在您的范围内正常工作,这意味着 std::sort 可能表现不正确。这也意味着您也无法将这些存储在 std::set 中,因为 std::set 内部以某种排序顺序(通常是平衡的二叉搜索树)存储所有内容,您可能会得到完全错误的结果。
希望这会有所帮助!
【解决方案2】:
如果a.first 小于b.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);
}
我觉得这更直观的理解,但逻辑是一样的:
【解决方案3】:
直觉在旁观者的眼中。其实我自己也觉得很直观。
它就像您在比较其他序列时所做的那样。例如,您会说字符串"az" 在"ba" 之前,对吗?但是你没有'a' < 'b' && 'z' < 'a'!同样的推理也适用于对。它不仅更直观,而且还保留了这种关系的所有理想属性。