【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 都相同的节点视为相等,不会违反严格弱序的要求。
总结起来,确保排序函数符合严格弱序是关键。如果两个节点在所有比较字段上都相同,并且你没有其他字段来区分它们,排序函数需要明确地处理这些情况,以避免段错误和未定义行为。

浙公网安备 33010602011771号