类内sort自定义排序函数需定义为static否则报错


本文动机为在刷力扣时遇到如下错误:
error:reference to non-static member function must be called

1. 使用sort算法自定义排序的几种方法及类内实现出现的问题

sort算法默认使用元素类型的 ‘<’ 运算符,但是当我们希望的排序顺序与 ‘<’ 所定义的顺序不同,或者我们的序列是未定义 ‘<’ 运算符的元素类型,这两种情况下,都需要重载sort的默认行为

通常,我们通过自定义一个cmp函数(官方称为谓词)作为sort的第三个参数来指定我们指定的排序规则,举例如下:

输入:给定一个二维数组envelopes,其中envelopes[i] = [wi, hi]分别表示信封宽度和高度;

排序规则:按信封宽度升序排列,对于宽度相同的信封,按高度降序排列。

用例:输入:envelopes = [[5,4],[6,4],[6,7],[2,3]],输出:[[2,3],[5,4],[6,7],[6,4]]

(注:这其实是力扣里面的一道hard题的一部分,详情见 LC #354 俄罗斯套娃信封问题

bool cmp(vector<int>& a, vector<int>& b) {
        if(a[0] != b[0]) return a[0] < b[0];
            else return a[1] > b[1];
    }
void testSort(vector<vector<int>>& envelopes) {
    sort(envelopes.begin(), envelopes.end(), cmp);
}

也可以不在外部显式定义cmp函数,而用lambda表达式实现谓词:

void testSort(vector<vector<int>>& envelopes) {
    sort(envelopes.begin(), envelopes.end(), 
        [](const vector<int>& a, const vector<int>& b){
            if(a[0] != b[0]) return a[0] < b[0];
            else return a[1] > b[1];
        });
}

但是,在刷力扣时,函数是实现在类内的,这时候采用方法一在类内定义cmp函数就会报错,代码和报错如下;

class Solution {
public:
    bool cmp(vector<int>& a, vector<int>& b) {
       if(a[0] != b[0]) return a[0] < b[0];
            else return a[1] > b[1];
    }
    int maxEnvelopes(vector<vector<int>>& envelopes) {
        int n = envelopes.size();
        // 下面这行排序会报错!
        sort(envelopes.begin(), envelopes.end(), cmp);
        vector<int> dp(n, 1);
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < i; j++) {
                if (envelopes[j][1] < envelopes[i][1]) {
                    dp[i] = max(dp[j] + 1, dp[i]);
                }
            }
        } 
        return *max_element(dp.begin(), dp.end());
    }
};

ffKSqe.png

分析:

查看sort源码(文末会贴出)会发现,sort的第三个参数,也就是我们自定义的cmp,只允许接收两个参数,而当在类内定义cmp函数时,如果像上述那样定义,在编译时,编译器会向函数添加隐式参数this,而变成了三个参数,所以编译会报错。

解决办法一:

将类内定义的cmp函数声明为static,此时cmp内不会加入this;

解决办法二:

将cmp函数定义在类外;

解决办法三:

直接用lambda函数。

2. sort部分源码:

sort有两个重载版本

ff196P.png

第一个版本只需传给它两个迭代器就可以了,此时默认升序排序,如下:

ffQhxP.png

第二个版本除了两个迭代器之外,还需要我们提供一个自定义的比较函数(谓词),如下:

ffl9ZF.png

此处暂且不讨论sort底层通过怎样的方式进行排序,有兴趣可以自己看下源码就明白了,这里我们关注一下sort对于第三个参数"__comp"是怎样定义的,从下图可以看出,__comp函数只接受两个参数,所以对于类内定义的cmp,因为会引入额外的this参数,导致报错。

ff1U6x.png

(注:从上图可以看出这里用了快排的方法,但sort算法的排序机制远不止如此的,具体实现另行探讨啦)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值