自己写泛型算法
最近有空写了一下LIS的算法实现,开始写得很安全但不通用,后来改成泛型的,通用但不安全。最终的版本可以下面这样用:
#include <iostream>
#include "LIS.h"
using namespace std;
int main(int argc, char* argv[])
{
vector<int> v;
copy(istream_iterator<int>(cin), istream_iterator<int>(), back_insert_iterator<vector<int> >(v));
cout << endl;
copy(v.begin(), v.end(), ostream_iterator<int>(cout, ","));
cout << endl;
LIS(v.begin(), v.end(), ostream_iterator<int>(cout, ","));
cout << endl;
cout << LIS_Length(v.begin(), v.end()) << endl;
system("pause");
return 0;
}
原型是这样:
OutIter LIS(InIter in_first, InIter in_last, OutIter out_first);
OutIter LIS(InIter in_first, InIter in_last, OutIter out_first, Pred pred);
计算[in_first, in_last)序列的Longest Increase Subsequence,输出到[out_first, out_last),返回out_last。pred是比较函数,不给用的是less<>。对迭代器有2个要求,输入的必须是随机访问迭代器,输出必须是输出迭代器(或以上),否则编译报错(报什么错要取决于你传入的参数类型,有可能就输出几百字)。
它没有对out_first后面的有效最大长度做检查,因此不安全,当然算法会告诉你 out_last - out_first <= in_last - in_first,你准备输入序列那么长肯定是足够的。
其实用纯C也能写出通用又安全的程序,比如qsort,但是总还是觉得不够优雅。当程序员这么久,可能都会有一种心理,就是,代码可以有bug,可以跑得很慢,但是不能写得很磋,程序员一生可能有1%的时间用在给代码起名字和整理代码上。没办法,新来的同事写对的程序,写得和你想的不同,不好看,也会让他改。
好了,简单说下泛型算法怎么写吧。
一般泛型算法的输入是一些迭代器描述的对象区间,如果算法和偏序相关还会给个比较函数,甚至一个配置器等。好了,这些东西全部定义成模板类,写个模板函数,1.0版本搞定。对于迭代器我们还要知道一些属性,比如元素类型,他是个什么样的迭代器,这些是用iterator_traits<T>提取出来的,它里面会把T的内部类型定义出来,同时对一些基本类型和原始指针都做了特化或偏特化,这样它就能把已有迭代器的属性提取出来,你如果自己开发新容器设计新的迭代器,只要按标准开发也能提取出来。
对于迭代器类型,是用一个内部类型表示的,像随机迭代器就是std::random_access_iterator_tag,再用这个类型定义一个辅助函数的辅助参数,利用C++参数重载规则进行选择,这里就会知道对于错误使用的输入编译错会报一个类型不能转换的错误。

浙公网安备 33010602011771号