【问题标题】:Custom sort works in an unexpected way自定义排序以意想不到的方式工作
【发布时间】:2020-08-09 04:00:52
【问题描述】:

我在以下针对我的矢量元素的自定义比较中得到了意想不到的结果。

int dateCompare(string d1,string d2)
{
    int rc;
    const char *d3 = d1.c_str();
    const char *d4 = d2.c_str();

    // compare years
    rc = strncmp(d3 + 6, d4 + 6, 4);
    if (rc != 0)
        return rc;

    // compare months
    rc = strncmp(d3 + 3, d4 + 3, 2);
    if (rc != 0)
        return rc;

    // compare days
    return strncmp(d3, d4, 2);
}


 vec.push_back("01/10/2015"); 
 vec.push_back("02/11/2015"); 
 vec.push_back("03/09/2015"); 
 sort(vec.begin(), vec.end(), dateCompare);

Input:
01/10/2015
02/11/2015
03/09/2015

Output:
03/09/2015
02/11/2015
01/10/2015

我知道还有其他更好的方法来比较日期和更改元素本身的结构等。但更重要的是,我想弄清楚为什么std::sort 函数的工作方式存在差异,即为什么无论比较器返回truefalse

,它都会交换

dateCompare() 为这 3 个元素调用了两次。

第一次 => 调用 dateCompare("02/11/2015","01/10/2015") 并在评估 strcmp(11,10) 期间返回 true,因此存在交换。所以 vec 从

{"01/10/2015","02/11/2015","03/09/2015"} to  {"02/11/2015","01/10/2015","03/09/2015"}

第二次 -> 调用 dateCompare("03/09/2015","02/11/2015") 并在评估 strcmp(09,11) 期间返回 false 预期不会发生交换,但仍然交换了。所以 vec 从

{"02/11/2015","01/10/2015","03/09/2015"} to {"03/09/2015","01/10/2015","02/11/2015"}

所以我更改了输入(03/09/2015 更改为 03/12/2015)以便第二个比较返回 true(而不是 false),但它仍然交换和结果:

01/10/2015
02/11/2015
03/12/2015


03/12/2015
02/11/2015
01/10/2015

无论返回是true 还是false,它看起来都交换了

【问题讨论】:

    标签: c++ algorithm sorting data-structures stl


    【解决方案1】:

    std::sort 期望比较器返回一个布尔值 - 如果第一个参数在排序顺序中应该在第二个参数之前,则返回 true,否则返回 false。像您一样返回 -1、0 或 1(表示小于、等于、大于)的比较器不适合 std::sort;它违反了严格弱排序的要求。您的程序表现出未定义的行为。

    【讨论】:

    • 在我的示例中,它返回 1 或 -1。 1 或 -1 是否不会转换为布尔值 true 或 false,我应该严格更改 1 和 -1 以返回 true 或 false?
    • 布尔上下文中的 1 和 -1 都是 true(任何非零整数都取为 true,零为 false)。所以你的比较器说,对于任何两个日期d1d2d1 应该在d2 之前,同时d2 应该在d1 之前 - 因此违反了严格的弱排序应该不对称(如果x < y,则!(y < x)
    猜你喜欢
    • 1970-01-01
    • 2017-10-29
    • 2015-05-31
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 2014-01-19
    • 2017-09-11
    相关资源
    最近更新 更多