什么是泛型算法
软件分数据和计算两部分,前面我们学的容器是对数据的封装,被称为数据结构。关于这些数据结构的计算在容器内部包含了一部分,如sort用来排序,但是没有提供更多,每一个容器内的的sort的实现方法不同,因为他们面对的是不同的容器,泛型算法是独立于容器类的一些操作方法,可以通用于多种容器,所以叫泛型,泛型算法有更高的抽象,实现起来难度更大,这也是STL的核心技术。使用STL算法库进行升序排序,示例代码如下。
vector<int> bb{4,2,1,3,5};
sort( bb.begin(), bb.end(), greater<int>() ); //传入迭代器和谓词,使其降序排列
for(auto x : bb)
{
cout << x <<" ";
}
谓词predicate引入
谓词就是可以做谓语的词,例如“我吃饭”,吃就是一个谓词,语义上含有动作。我们程序中的函数就是一个典型的谓词。如上例中,调用的greater<int>()就是一个STL库提供的谓词,常见的谓词可以是函数(函数指针)、函数对象(库函数对象)和lambda表达式,形式上类似bool func(T &a)或者bool func(T &a, T &b),其特点是返回值都为bool,输入都是引用类型。谓词接收1个参数就叫一元谓词,接收2个参数就叫二元谓词。
函数对象引入
函数对象 function object,也叫仿函数,是一个长得像函数的对象,他不是真的函数,只是在调用形式上像是个函数,实际上他是一个类,而在类中做了小括号“()”的运算符重载,如上例中的greater<int>(),他其实就是greater对象中的一个operator( )小括号运算符重载,当然他运算符重载也是一个函数,所以背后还是调用了一个函数,其底层实现方法如下示例。
template( typename T ) class greater
{
public:
T operator()(T a) //()运算符重载
{
if(a>0) return 1; return 0;
}
};
greater<T> func; //定义一个对象
int b = func<T>(5); //调用类中运算符重载函数。
自定义谓词
如下示例,定义了一个aa类,在类中写了一个括号的运算符重载函数,在内部实现字符串比较,再调用STL的sort方法来对数据排序,同时把我们自己写的类传进去,即可实现按照我们自己定义的对比方法来排序,STL算法库中大多函数只负责做自己的功能,但是关键的判断,需要外部提供,如sort只负责排序,到底从大到小还是由多变少这些判断都由谓词来提供sort只根据谓词返回值来做排序,简单说就是怎么对比由我们提供的谓词决定。谓词的应用和函数回调非常类似,都是向一个函数传入一个函数。
class aa
{
public:
bool operator()(const string &a,const string &b) //二元谓词
{
return (a.size()>b.size());
}
};
array<string,3> bb{"hu","dai","zhou"};
sort( bb.begin(), bb.end(), aa() );