sort/stable_sort 自定义比较功能导致一些奇怪的问题

Posted

技术标签:

【中文标题】sort/stable_sort 自定义比较功能导致一些奇怪的问题【英文标题】:Sort/stable_sort custom compare function cause some strange issues 【发布时间】:2020-01-21 03:00:51 【问题描述】:

我对 sort/stable_sort API 的自定义函数有非常基本的经验。 下面是我在 Windows Visual Studio 2017 下运行的源代码。 请帮助分析是什么问题,我错过了什么或者背后的理论是什么?感谢您的帮助

// 10_3_1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;
#define MAX_INPUT_NO    (10u)

typedef bool(* sort_func_t)(const int input_a, const int input_b);

bool is_shorter(const int input_a, const int input_b)

#if 0
    //this portion will show the iteration overlap
    if (input_a > input_b)
        return false;
    else
        return true;
#else
    //both below works
    //return input_a < input_b;
    return input_a > input_b;

#endif


void elimDups(vector<int> &dat, sort_func_t func)

    vector<int>::iterator temp = dat.begin();
    std::stable_sort(dat.begin(), dat.end(), func);
    //sort(dat.begin(), dat.end());

    temp = unique(dat.begin(), dat.end());
    dat.erase(temp, dat.end());


void print_vec(vector<int> &dat)

    vector<int>::const_iterator index = dat.cbegin();
    int i = 0;
    for (; index < dat.cend(); index++)
    
        cout << "dat[" << i << "] = " << dat.at(i++) << endl;
    


int main()

    vector<int> a;
    int ia[MAX_INPUT_NO] = 0, 1, 2, 1, 2, 3, 1, 2, 4, 5;
    a.assign(ia, ia + MAX_INPUT_NO);
    print_vec(a);
    elimDups(a, is_shorter);
    print_vec(a);

    getchar();
    return 0;


但我在玩 if-else 部分时遇到的问题是,它给了我无效的比较器断言错误。

    如果我像下面这样定义自定义函数,使用 if-else 模式,它可以正常工作。
bool is_shorter(const int input_a, const int input_b)

#if 1
    //this portion will show the iteration overlap
    if (input_a > input_b)
        return true;
    else
        return false;
#else
    //below works
    return input_a > input_b;
#endif

下面是我得到的结果。

期待第 1 项的结果

    如果我像下面这样定义自定义比较器函数,它也使用 if-else 模式,它将失败并出现“无效比较器”错误。
bool is_shorter(const int input_a, const int input_b)

#if 1
    //this portion will show the iteration overlap
    if (input_a > input_b)
        return false;
    else
        return true;
#else
    //below works
    return input_a > input_b;
#endif

以下是我收到的错误消息:

来自 Visual Studio 2017 的错误消息

    但如果我只使用 return,那么它在两个方向上都可以正常工作。
bool is_shorter(const int input_a, const int input_b)

#if 0
    //this portion will show the iteration overlap
    if (input_a > input_b)
        return false;
    else
        return true;
#else
    //both below works
    //return input_a < input_b;
    return input_a > input_b;

#endif

【问题讨论】:

自定义比较器必须有严格的弱排序。 &lt;&gt; 的关系都具有严格的弱排序,但 &lt;=&gt;= 没有。它失败了,因为比较器在input_a &lt;= input_b 时返回true 【参考方案1】:

这段代码:

if (input_a > input_b)
    return false;
else
    return true;

是一种复杂的说法:

return !(input_a > input_b);

greater then 的否定是less or equal

return input_a <= input_b; // logically same as before

问题是您不能使用less or equal 关系进行排序,因为它不提供算法所需的严格弱排序。不过你可以少用:

return input_a < input_b;

或大于您在代码中使用时所使用的。

【讨论】:

如果调试构建完成,Visual Studio 的某些(或全部?)版本将捕获 @Slava,感谢您的解释。 @zengweitotty 请阅读What should I do when someone answers my question?

以上是关于sort/stable_sort 自定义比较功能导致一些奇怪的问题的主要内容,如果未能解决你的问题,请参考以下文章

idea自定义数据导出格式

优先队列的自定义比较功能

Configure FileMenu Tools(自定义/扩增右击功能) 原来右击功能还可以有这么多强大的操作

vscode 自定义导包失败问题

使用自定义比较功能对列表列表进行排序

javascript中是不是有indexOf来搜索具有自定义比较功能的数组