我们先来看一个剑指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;
}