C++标准库之泛型算法(一)——泛型算法概述(C++ Primer)

一、迭代器(头文件iterator)

(一)、按照操作权限分

1. 容器自带的迭代器
  • 主要包含begin()、end()、cbegin()、cend()返回的迭代器,这些迭代器只能访问容器中已有的元素
2. 插入迭代器(insert iterator)
 *iter, ++iter, iter++这些操作虽然存在,但不会对iter做任何操作,每个操作都返回iter;
 所以back_inserter始终指向尾后;front_inserter始终指向开始前;inserter始终指向初始值的位置
  • 主要操作:插入数值 *iter = val;
  • back_inserter: 创建一个使用push_back的迭代器
  • front_inserter:创建一个使用push_front的迭代器
  • inserter:有两个参数(容器变量名,容器迭代器)
3. iostream迭代器(不支持自减运算与复制,可以引用)
3.1 istream_iterator的操作:
  • 初始化:用一个输入流对象来作值初始化;默认初始化为尾后位置;
    istream_iterator in(cin); //in从输入流cin读取类型为T的值
  • 支持==和!=关系运算符
  • 支持解引用及调用 is_iter->mem
  • 支持前置和后置递增运算,表示读取下一个值;不支持自减运算符;cin会随着输入自动指向下一个位置
  • istream_iterator允许使用惰性求值(也就是输入有缓存)标准库的实现保证:在我们第一次解引用迭代器之前,从流中读取数据的操作就已经完成了。
    但如果我们创建了一个istream_iterator,没有使用就销毁了,或者我们正在从两个不同的对象同步读取同一个流,那么何时读取就很重要了。
3.2 ostream_iterator的操作:
  • 初始化:ostream_iterator必须指定一个流,不允许空的或表示尾后位置的ostream_iterator out;//默认初始化
    ostream_iterator out (os, d); //out将类型为T的值写入输出流os,每个值后面都输出d指向以一个空字符结尾的字符数组),d可以缺省。
  • out = val; // 相当于*out = val;*out不对out做任何事情,但最好写成 *out = val;
  • *out, ++out, out++这些操作虽然存在,但不会对it做任何操作,每个操作都返回out;out会随着输出自动指向下一个字符。
4. 反向迭代器
  • 反向迭代器从容器的后面反向访问元素,自增、自减操作与迭代器的方向相反
  • 只有支持–的迭代器才能定义反向迭代器
  • 由于迭代器范围的集合是左闭右开的(不对称的),所以反向迭代器与迭代器的范围不一致,造成:
    反向迭代器的位置在迭代器左边一个位置;关系如下:
    c.begin() == c.rend().base();
    c.end() == c.rbegin().base();

(二)、泛型算法中的迭代器类别(iterator category)

在用泛型算法处理问题时,要注意传入的迭代器要跟算法要求的迭代器兼容
1. 输入迭代器(input iterator)
 只读,不写;单遍扫描,只能递增;标准IO输入的迭代器istream_iterator、const_iterator属于此类
  • 用于比较两个迭代器相等和不相等的运算符(!= ==);
  • 用于推进迭代器的前置和后置递增运算;
  • 用于读取元素的解引用运算符:解引用运算符只会出现在运算符的右侧;
  • 箭头运算符(->):解引用迭代器,并提取对象的成员。
2. 输出迭代器(output iterator)
只写,不读;单遍扫描,只能递增;标准IO输出的迭代器ostream_iterator属于此类
  • 用于推进迭代器的前置和后置递增运输;
  • 解引用运算符:解引用运算符只会出现在运算符的左侧;
3. 前向迭代器(forward iterator)
可读写;多遍扫描,只能递增;forward_list支持的迭代器属于此类
4. 双向迭代器(bidirectional iterator)
可读写;多遍扫描,可递增递减;除forward_list外,其他标准容器都支持双向迭代器
5. 随机访问迭代器(random-access iterator)
可读写;多遍扫描,支持全部迭代器运算;标准容器array、deque、string 和 vector支持
  • 全部运算包含:关系运算符、与整数值的加减运算、两个迭代器的相减、下标运算

二、特定容器算法

针对标准容器list和forward_list
1. 跟泛型算法不同版本的算法
  • lst.merge(lst2); 或lst.merge(lst2, cmp);//将lst2中的元素按序并入lst,(lst和lst2必须有序),合并后lst2变为空。通过<运算符或定制比较操作来合并。
  • lst.remove(val); 或 lst.remove_if(predicate); //调用erase删除掉与val相等的,或是predicate返回真的元素。
  • lst.sort(); 或 lst.sort(cmp); //使用<或给定的比较操作排序元素
  • lst.unique(); 或lst.unique(pred); //调用erase删除同一个值的连续拷贝。第一个版本使用==;第二个版本使用给定的二元谓词。
    //此处跟泛型算法不同,泛型算法返回不重复序列之后位置,而此处直接删除不重复序列之后的元素
2. splice算法(链表数据结构特有的)
2.1 splice 和 splice_after跟insert、insert_after相似,有两点不同
  1. splice中的第一个参数必须为链表容器的对象;
  2. splice的插入是移动方式,插完,arg中元素就没了元素只有一个备份,insert是复制arg中元素来插入。
2.2 arg_list 的类型有:(p,lst2); (p, lst2, p2); (p,lst2, b,e)

你可能感兴趣的:(C++,泛型算法)