【C++ Primer】泛型算法(待修改)

十一、泛型算法


应包含头文件<algorithm> , 一些算术算法应该包括<numeric>

大多数情况下,算法都需要使用(至少)两个迭代器来指出算法操作的元素范围,第二个迭代器指向最后一个元素的下一位置,比如说ivec.end();


1. 只读算法

accumulate(iter, iter, initail)    第三个形参是累加的初值;

find_first_of(it1, it1end, it2, it2end)   it1和it2只要能进行比较即可


2. 写算法

fill(it1, it2, initial)  只会对有效的范围进行写入


当写算法中需要写入到另外的迭代器时,一定要注意容器的大小

vector<int> vec;

fill_n(vec.begin(), 10, 0);  // 错误! vec为空,不能执行加操作! 可以变成fill_n(back_inserter(vec), 10, 0)


replace(iter1, iter2, replaced_value, new_value) 每一个等于第一个值的元素将被替换为第二个值。


copy版本:

copy(ilst.begin(). ilst.end(), back_inserter(vec))效率比不上直接初始化

replace_copy(iter1, iter2, newiter, replaced_value, new_value)



3. 排序算法

sort(it1, it2, 比较函数(可选、谓词函数))      默认按从小到大顺序排列

stable_sort(it1, it2, 比较函数(可选))   稳定排序,相对位置不会改变


unique(iter1, iter2)  不改变容器大小!将重复元素放到容器后面,返回指向第一个重复的元素的迭代器


count_if(iter1, iter2, 比较函数)



4. 迭代器

定义在头文件iterator中


插入迭代器:

迭代器适配器,与容器绑定在一起,产生与该容器绑定的插入迭代器,用于实现在容器中插入元素:

back_inserter(容器)  使用push_back实现

front_inserter(容器)  使用push_front实现插入,需要支持push_front()操作,vector不可以,

inserter(容器, iter)  使用insert实现插入


iostream迭代器: 支持自增不能自减

与输入或输出流绑定到一起,用于遍历所关联的IO流。iostream虽然不是容器,但是标准库同样提供了在iostream对象上使用的迭代器。istream_iterator用于读取输入流,ostream_iterator用于写入到输出流。使用流迭代器时,可以使用泛型算法从流对象中读取数据

istream_iterator(strm)   不传入strm参数则表示超出末端迭代器

ostream_iterator(strm, delim)   delim可以没有,表示分隔符


1:istream_iterator in(strm);//创建从输入流strm中读取T类型对象的istream_iterator对象。

2:istream_iterator<T> in;//istream_iterator对象的超出末端迭代器。

3:ostream_iterator<T> in(strm);//创建将T类型的对象写到输出流strmostream_iterator对象。

4:ostream_iterator<T> in(strm,delim);//创建将T类型的对象写到输出流strmostream_iterator对象,在写入的过程中使用delim作为元素的分隔符。delim是以空字符结束的字符数组。

例如:

istream_iterator<int> cin_it(cin);

istream_iterator<int> end_of_stream;

vector<int> vec(cin_it, end_of_stream);

ostream_iterator<int> output(cout, " ");

unique_copy(vec.begin(), vec.end(), output);


反向迭代器:用于实现从后向前遍历,所有容器类型都有定义了自己的反向迭代器类型。由rbeginrend返回。

反向迭代器可以使用r.base()转换为正向迭代器,为了降序排列vector可以向sort传递一对反向迭代器。



5. 算法类型

alg(beg, end, other parms)

alg(beg, end, dest, other parms)  带有单个目标迭代器的算法,必须确保容器足够的存储空间


alg(beg, end, beg2, other parms)   指定了第二个输入范围的首元素, 同样必须确保足够存储空间


alg(beg, end, beg2, end2, other parms)  


容器特有算法:

list.merge(lst2) 使用<操作符,lst2被清空

list.merge(lst2, comp)  使用comp指定的比较运算


lst.reverse()

lst.sort()

list.unique()  删除相同元素,不同于泛型算法中的unique


算法要求用于指定范围的两个迭代器具有完全一样的类型。调用m.end()返回的类型,依赖于m的类型。如果mconst对象则返回const_iterator类型,否则返回普通的迭代器。

算法要求的迭代器分为五个类别,分别为:

1:输入迭代器,读,不能写,只支持自增运算。只能顺序使用,一旦自增就不能检查之前的元素。

2:输出迭代器。写,不能读,只支持自增运算。对于指定的迭代器应该使用一次*运算,而且只能使用一次。

3:前向迭代器,读和写,只支持自增运算。用于读写指定的容器,这个迭代器只会以一个方向遍历序列。它支持对一个元素的多次读写。

4:双向迭代器,读和写,支持自增和自减运算。从两个方向读写容器。所有标准库提供的迭代器都至少达到双向迭代器的要求。

5:随机访问迭代器。读和写,支持完整的迭代器算术运算。提供在常量的时间内访问容器任意位置的功能。需要随机访问迭代器的泛型算法包括sort算法,vectordeque,string迭代器都是随机访问迭代器。用作访问数组元素的指针也是随机访问迭代器。

除了输出迭代器外,其他类别的迭代器形成了一个层次结构:需要低级类别迭代器的地方,可以使用任意一种更高级的迭代器。对于需要输入迭代器的算法,可传递向前、双向或随机访问迭代器。而需要随机访问迭代器时,必须传递随机访问迭代器。

map,set和list类型提供双向迭代器。而stringvectordeque容器上定义的迭代器是随机访问迭代器,用作内置数组元素的指针也是随机访问迭代器。istream_iterator是输入迭代器,ostream_iterator为输出迭代器。

注意:尽管map,set类型提供双向迭代器,但关联容器只能使用算法的一个子集,这是因为:关联容器的键是const对象。因此关联容器不能使用任何写序列元素的算法。

你可能感兴趣的:(【C++ Primer】泛型算法(待修改))