C++:泛型算法基础
来源:互联网 发布:无尽之剑3宝石数据修改 编辑:程序博客网 时间:2024/05/01 19:02
泛型算法
顺序容器只定义了很少的操作,我们希望容器支持更多的操作。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++:泛型算法基础
- C语言算法基础
- C语言基础算法
- 算法基础--C++OJ
- 【C#】泛型基础
- 基础算法--C快速排序
- 算法导论C语言实现: 算法基础
- 泛型算法基础习题
- c语言算法—01背包问题(基础型)
- 【C++】:C++泛型基础
- 《C++primer》 泛型算法
- 经典排序算法基础篇(C++)
- C语言算法(一)基础
- 算法基础部分-C语言表示
- 基础搜索算法题解(A-C)
- C语言中三个基础算法
- c语言基础算法(一)---排序
- C语言基础 16 二叉树 算法
- UNIX 目标文件
- 13、设计模式——单例模式
- 1025. 反转链表 (25)
- JAVA 正则表达式截取字符串小例子
- python学习
- C++:泛型算法基础
- Mac 相关命令行
- html css学习笔记-水平与垂直导航
- POJ 1987 Distance Statistics 树上点分治
- 第八周项目1-实现复数类中的运算符重载(1)
- c语言查漏补缺
- android中动态添加组件
- 黑马程序员---java中的接口详解与用例
- Cg语言学习笔记(2)