STL伪函数应用

来源:互联网 发布:wps for mac好用吗 编辑:程序博客网 时间:2024/05/23 14:44

我们先来看一个剑指offer中的编程练习题吧:

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

这个编程练习并不难,有两个关键点:
①在于int和string之间的转换方便排序;
②在排序时要完成两个记录的全排列再比较。

看到在排序时需要特殊操作,我们完全可以借助STL提供的sort函数完成我们需要的操作
具体代码如下:

#include<iostream>#include<string>#include<vector>#include<algorithm>using namespace std;     bool cmp(string st1, string st2)        {            string s1 = st1 + st2;            string s2 = st2 + st1;            return s1 < s2;        }    string PrintMinNumber(vector<int> numbers) {        string result;        if (numbers.size() == 0)            return result;        vector<string> strNum;        for (int i = 0; i<numbers.size(); i++)     //完成转换        {            strNum.push_back(to_string(numbers[i]));        }        sort(strNum.begin(), strNum.end(),cmp );   //根据特定规则排序        for (int i = 0; i<numbers.size(); i++)        {            result += strNum[i];        }        return result;};int main(){    vector<int> temp = { 3, 32, 321 };    string res = PrintMinNumber(temp);    cout << res << endl;    cin.sync();    cin.get();    return 0;}

这里写图片描述

很容易就得到我们需要的答案。

然而我们习惯将函数封装在类中,因此我们将程序修改为

#include<iostream>#include<string>#include<vector>#include<algorithm>using namespace std;class Solution {public:        bool cmp(string st1, string st2)        {            string s1 = st1 + st2;            string s2 = st2 + st1;            return s1 < s2;        }    string PrintMinNumber(vector<int> numbers) {        string result;        if (numbers.size() == 0)            return result;        vector<string> strNum;        for (int i = 0; i<numbers.size(); i++){            strNum.push_back(to_string(numbers[i]));        }        sort(strNum.begin(), strNum.end(),cmp );        for (int i = 0; i<numbers.size(); i++)        {            result += strNum[i];        }        return result;    }};int main(){    vector<int> temp = { 3, 32, 321 };    Solution a;    string res=a.PrintMinNumber(temp);    //string res = PrintMinNumber(temp);    cout << res << endl;    cin.sync();    cin.get();    return 0;}

然而这样是的结果是
error C3867: “Solution::cmp”: 函数调用缺少参数列表;请使用“&Solution::cmp”创建指向成员的指针

那么问题的原因在于,我们在使用STL泛类编程的过程中,对容器中的元素要进行批量操作,确实可以通过指针完成,但是这有极大的弊端,那就是必须指定参数以及返回类型,而这对于STL来说是违反泛类编程的本质思想的。

好像扯远了

直接说对于上面两段代码 根本区别在于这里

sort(strNum.begin(), strNum.end(),cmp );

cmp的类型应该是:
①函数对象(伪函数);
②全局指针。

在第二段代码中,将cmp封装在Solution类中,cmp不在是全局函数指针,因此出现了参数不匹配的情况。

对此啊,有两种处理方法

①将cmp方法改为静态成员即可;

static bool cmp(string st1, string st2)

②使用伪函数代替成员函数

什么是伪函数(functor)?函数对象是一种介于对象和函数之间的一个东西,调用方式和函数一样,但是调用的却是对象里的operator ()操作符,这可以给程序带来三大好处。
第一,面相对象里的模板机制对functor是完全适用的,因此用函数对象可以和STL完全兼容,换句话说,使用functor和泛型的思想相符。
第二,函数对象本质上是对象,因此,一个函数对象可以使用类中所封装的所有数据,而对于函数指针来说,只能使用全局数据,所以,使用functor可以达到数据封装的目的。
第三,functor往往是轻量级代码,因此,可以完美内联化,这对于程序效率的提升是非常有利的。

说了这么多 看看这段代码该怎么改很容易就理解的

#include<iostream>#include<string>#include<vector>#include<algorithm>using namespace std;class Solution {public:    struct compare{                         //伪函数        bool operator()(string st1, string st2)        {            string s1 = st1 + st2;            string s2 = st2 + st1;            return s1 < s2;        }    };    string PrintMinNumber(vector<int> numbers) {        string result;        if (numbers.size() == 0)            return result;        vector<string> strNum;        for (int i = 0; i<numbers.size(); i++){            strNum.push_back(to_string(numbers[i]));        }        sort(strNum.begin(), strNum.end(),Solution::compare() );        for (int i = 0; i<numbers.size(); i++)        {            result += strNum[i];        }        return result;    }};int main(){    vector<int> temp = { 3, 32, 321 };    Solution a;    string res=a.PrintMinNumber(temp);    //string res = PrintMinNumber(temp);    cout << res << endl;    cin.sync();    cin.get();    return 0;}
0 0