【C++】关于cmp函数的一点细节
【今日刷算法题遇到一个测试点总是段错误,把所有可能的地方都修了一遍发现是cmp加了取等的问题,遂记录之:】
在排序时,如果将比较函数写成
bool cmp(Node n1, Node n2) { if (n1.x==n2.x) return n1.y>=n2.y; return n1.x>n2.x; }
可能会导致段错误(segmentation fault)。其原因主要与排序算法的要求有关。
标准库中的排序算法( std::sort
)要求比较函数满足 严格弱序(strict weak ordering)条件。严格弱序要求满足以下几个条件:
- 非自反性(Irreflexivity):对于任何元素
a
,comp(a, a)
返回false
。 - 反对称性(Antisymmetry):对于任何元素
a
和b
,如果cmp(a, b)
为true
,则cmp(b, a)
必须为false
。 - 传递性(Transitivity):对于任何元素
a
,b
和c
,如果cmp(a, b)
为true
,且cmp(b, c)
为true
,则cmp(a, c)
也必须为true
。
比较函数:
bool cmp(Node n1, Node n2) {
if (n1.x == n2.x) return n1.y > n2.y;
return n1.x > n2.x;
}
满足严格弱序,因为它明确区分了 n1.y
和 n2.y
的比较。
而比较函数:
bool cmp(Node n1, Node n2) {
if (n1.x == n2.x) return n1.y >= n2.y;
return n1.x > n2.x;
}
则不满足严格弱序。具体来看,如果 n1
和 n2
的 x
值相等且 n1.y
等于 n2.y
,此时 n1.y >= n2.y
返回 true
,而 n2.y >= n1.y
也会返回 true
,这会违反反对称性(Antisymmetry),导致排序算法无法正常工作,从而引发段错误。
如果两个 Node
对象的 x
和 y
值都相同,那么从严格意义上讲,它们是不可区分的。在这种情况下,排序函数的行为确实应该表明这些对象是相等的,以满足严格弱序的要求。 如果不需要进一步区分它们,那么可以保持原来的比较函数:
bool cmp(Node n1, Node n2) {
if (n1.x == n2.x) return n1.y > n2.y;
return n1.x > n2.x;
}
这种情况下,排序算法会将 x
和 y
都相同的节点视为相等,不会违反严格弱序的要求。
总结起来,确保排序函数符合严格弱序是关键。如果两个节点在所有比较字段上都相同,并且你没有其他字段来区分它们,排序函数需要明确地处理这些情况,以避免段错误和未定义行为。