简介
算法大多不依赖于特定的容器类型,是“泛型”的,可作用在不同类型的容器和不同类型的元素上,不但可以用在vector、list上,还可以用在内置数据类型、甚至其它类型的数据上。
概述
- 迭代器将算法与容器绑定起来
- 算法从不使用容器操作,元素的访问和遍历都是通过迭代器实现
- 算法也许会改变容器中元素的值,但是从不会直接添加和删除元素
初窥算法
- 泛型算法的头文件是<algorithm>
- 泛化的算数算法<numeric>(以后体会)
- 只读算法accumulate(一对迭代器实参,累加) find_first_of(两队迭代器实参)
- 写容器的安全算法:(调用容器的push_back方法)
back_inserter是迭代器适配器,生成一个适应其形参行为的新对象vector<int> vec; fill_n(back_inserter(vec),10,0)
- 泛型算法:stable_sort和count_if,用到谓词函数,从而可以按照自己的意愿进行统计。
bool GT6(const string &s) { return s.size() >=6; } vector<string>::size_type wc = count_if(words.begin(),words.end(),GF6);
再谈迭代器
- 插入迭代器: back_iterator(用push back实现插入),front_iterator,inserter,可以保证容器大小安全
- 纠正书上错误 P349页 通过front_iterator插入元素的结果为3,2,1,0 通过inserter插入的元素结果为0,1,2,3(书上没错)
list<int> ilist1.ilist2,ilist3; //ilist1:3,2,1,0 for(list<int>::size_type i =0;i!=4;i++) { ilist1.push_front(i); } //ilist2:0,1,2,3 copy(ilist.begin,ilist1.end,front_iinserter(ilist2)); //ilist3:3,2,1,0 copy(ilist.begin,ilist1.end,inserter(ilist3,ilist3.begin()));
IOSTREAM迭代器
- 任何定义输入操作符(>>操作符)的类型都可以定义istream_iterator
//将iterator绑定在输入流上 istream_iterator<int> cin_it(cin); //没有实参,则该迭代器指超出末端的位置 istream_iterator<int> end_of_stream //常用 while(cin_it != end_of_stream)
- 在创建ostream_iterator对象时,可提供第二个可选的实参,指定将数据写入输出流的分隔符,但必须是C风格的字符串,必须以空字符结束
ofstream outfile; ostream_iterator<Sales_item> output(outfile," ");
- 有趣的赋值方法:
istream_iterator<string> in_iter(cin); istream_iterator<int> eof; vector<int> vec(in_iter,eof);
- 限制:a不可以从ostream_iterator对象读入,也不可能写到istream_iterator中; b一旦给ostream_iterator对象赋了一个值,写入就提交了,没办法再改变 c.ostream_iterator没有->操作符
五种迭代器
- 输入迭代器:一旦输入迭代器递增了,就无法用它检查之前的元素。这个层次上提供支持的泛型算法包括find和accumulate
- 输出迭代器,只能使用一次*运算
- 前向迭代器:支持输入和输出迭代器所有的操作,还支持对同一元素的多次读写。只支持一个方向,因此只支持自增,这个层次上提供支持的泛型算法包括replace
- 双向迭代器:支持自增和自减,所有标准库容器提供的迭代器至少达到双向迭代器的要求,map,set,list提供的双向迭代器,但是注意由于键值是const的,不能写。
- 随机迭代器:提供常量时间内访问容器任意位置的功能。sort算法。string 、vector、 deque容器定义的是随机迭代器
- 对于每一个形参,迭代器必须保证最低功能
泛型算法结构
- 算法的形参模式:带有单个目标迭代器与带第二个迭代器组,都需要确保输出容器有足够大的容量存储输出数据
- 谓词参数用法 : sort(beg,end,cmp) find_if(beg,end,pred):用于查找一个使谓词函数pred非零值的元素
容器特有的算法
- 标准库为list容器定义了更精细的操作集合,可以不依赖与泛型操作,提高性能,对于list对象,应该优先使用list容器特有的成员版本,而不是泛型算法
- 与对应的泛型算法不同,list容器特有的操作能添加和删除元素。例如remove\unique修改了其关联的基础容器,merge和splice运算会破坏它们的实参。