C++:泛型算法基础
2015-05-16 10:49
232 查看
泛型算法
顺序容器只定义了很少的操作,我们希望容器支持更多的操作。C++标准库为了满足更多开发者的需求,实现了一些经典算法的公共接口,因为这些算法不依赖于具体的容器,而是借助迭代器对容器进行操作,所以常称其为泛型算法。泛型算法都定义在
<algorithm>头文件中,少数数值型算法定义在
<numeric>头文件中。
一般情况下,算法不会直接操作容器,而是借助容器的迭代器来遍历、操作容器中的元素。而且,大多数算法绝对不会改变容器的长度。(erase和insert等操作不是算法,而是“容器操作”,注意分清)
算法分类
只读算法
只读算法会读取输入范围内的元素,而绝对不会改变元素,这种情况下我们一般使用常量迭代器。find:
auto it = find(intVec.cbegin(), intVec.cend(), value); if (it != intVec.cend()) cout << *it << endl;
find查找容器中是否存在值为value的元素,如果不存在返回尾后迭代器。
accumulate:
auto sum = accumulate(intVec.cbegin(), intVec.cend(), 0);
accumulate定义在
<numeric>头文件中,用来求容器中一段范围的和,第三个参数是sum的初始值,注意初始值的选取和容器中元素的类型是有关系的。如果是double型要初始化为0.0.
值得一提的是,accumulate并不支持所有的元素类型。
元素类型必须定义了“+”操作才可以用accumulate。
例如:
vector<char*> vec ={ "i am" , "you are"}; auto sum = accumulate(vec.cbegin(),vec.cend()," ");
因为char*并不支持‘+’操作,所以编译器报错,如果是
vector<string>是可以的。
equal:
equal算法用于确定两个序列是否保存相同的值。
equal(c1.cbegin(), c1.cend(), c2.cbegin());
该算法接收三个迭代器。前两个迭代器表示第一个序列的范围,第三个迭代器是第二个序列的起始迭代器位置。这个算法基于这样的编程假设:
1.c1和c2容器类型不必相同,但是容器中的元素类型必须相同
2.容器中的元素类型必须支持“==”操作。(例如某些自定义类可能没有重载“==”运算符,那么就不能用该算法)
3.第二个序列的长度至少和第一个序列的长度相同
写操作算法与迭代器适配器
前边曾经提到过,绝大部分算法不会修改容器的长度,这好像限制了某些操作。例如:
fill_n:
fill_n算法原型
fill_n(dest,n,val)向目标位置dest填充n个值为val的元素,dest是一个迭代器。
vector<int> intVec;//空容器 fill_n(intVec.begin(), 10, 0);
这里运行会报错。因为规定算法不可以修改容器的长度,此时容器长度为0。这一点很容易出现致命错误,因为编译器不会检查算法的写操作是否合法,需要程序员保证。
我们可以先分配给intVec一些空间后,再指向fill_n操作。
intVec.resize(20); fill_n(intVec.begin(), 10, 0);
注意这里是resize而不是reserve。vector 的reserve增加了vector的capacity,但是它的size没有改变!而resize改变了vector的capacity同时也增加了它的size!
除了刚才的方法,还可以用一种叫做”插入迭代器”的方式来得到我们期望的结果。
插入迭代器
back_inserter是一种”迭代器适配器“。
适配器是一种接口转换器,它可以让一种东西看起来像另一种东西。
在这里
back_inserter使得迭代器能够像函数
push_back进行一样的操作,它使得一个迭代器看起来像是调用了
push_back一样。
fill_n(back_inserter(intVec), 10, 0);//添加10个0到intVec中去
这里在提醒一下,我们之前说过算法不可以改变容器的size,那这里为什么可以成功运行不出错呢?
原因在于,算法操作了一个迭代器,迭代器可以完成向容器中添加元素的功能,但是算法本身永远不会这么做,所以和我们之前说的并不矛盾。
auto it1 = back_inserter(intVec);//插入器绑定到了intVec上并且生成了一个迭代器it *it1 = 10;//相当于intVec.push_back(10)
除了
back_inserter之外还有
front_inserter(调用
push_front)和
inserter调用容器操作的
inserter。
例如:
auto it3 = inserter(intVec, intVec.begin())在intVec.begin()位置之前调用
insert()容器操作。
当然,
vector<typename>并不可以使用
front_inserter(),因为
vector<typename>上没有定义
push_front操作。
copy:
copy向一个目标位置写入一定范围内的数据。
这个算法接受三个迭代器
copy(it1,it2,dest)表示将[it1,it2)范围内的元素copy到dest为起始位置的序列(dest是一个迭代器).
由于copy是算法不会改变目标容器的长度,所以下述操作是错误的:
vector<int> l; copy(intVec.cbegin(), intVec.cend(), l.begin());
l是空容器,l.size() == 0,copy不可以改变其size所以操作出错。可以预先改变l的size或者利用
back_inserter
改变l的size:
vector<int> l; l.resize(100); copy(intVec.cbegin(), intVec.cend(), l.begin());
利用
back_inserter
vector<int> l; copy(intVec.cbegin(), intVec.cend(), back_inserter(l));
replace:
replace操作替换某一段区间的值
replace(it1,it2,value,aim_value)将[it1,it2)区间内的value值替换为aim_value
replace(l.begin(), l.end(), 0, 101);
将l的所有0替换为101.
相关文章推荐
- C++语法基础--泛型算法(generic algorithm)--replace_copy(),unique_copy,copy()
- C++语法基础--泛型算法(generic algorithm)--iostream迭代器
- C++语法基础--泛型算法(generic algorithm)--写入容器元素的算法fill(),fill_n,replace()
- C++语法基础--泛型算法(generic algorithm)--插入迭代器back_inserter(),front_insertor(),inserter()以及next()函数简介
- C++语法基础--泛型算法(generic algorithm)--对容器排序的算法sort(),stable_sort(),unique()
- C++语法基础--泛型算法(generic algorithm)--反向迭代器,reverse_iterator::base()
- C++语法基础--泛型算法(generic algorithm)--transform
- C++语法基础--泛型算法(generic algorithm)--find(),find_if()
- C++语法基础--泛型算法(generic algorithm)--只读算法accumulate(),find_first_of(),count(),count_if()
- C++——算法基础之排序——快速排序
- 算法与数据结构基础8:C++实现有向图——邻接表存储
- C++——算法基础之动态查找表1——二叉排序树
- 3 算法训练 乘法表(基础题) C++
- C++ 泛型算法及迭代器概述
- C++学习笔记29——泛型算法之插入迭代器
- C++程序设计:基础、编程抽象与算法策略的笔记
- c++ 泛型算法 使用方法总结
- [置顶] 信息学奥赛一本通(C++版) 第二部分 基础算法 第一章 高精度计算
- STL + c++ + 模板 + 重要思维 + 基础算法+ 经典算法 + 经典实例 + 编程总结+ 心得+ 入门必会 + 知识点汇总。+string +dfs +bfs等重要算法
- 心动C++ 情牵基础算法III