【C++Primer】泛型算法简述

1、引言

泛型算法
大多数算法都定义在头文件algorithm中,标准库的头文件numeric中定义了一组数值型算法。泛型算法的作用是通过迭代器间接访问容器,不会执行容器的操作,只运行在迭代器之上,迭代器可以做什么,泛型算法就可以做什么。 迭代器算法不依赖于容器,但算法依赖于元素类型的操作。

2、初识泛型算法

2.1写容器元素的算法

关于迭代器参数:常见的迭代器参数有a.begin()和a.end(),如果出现一些算法从两个序列中读取元素,构成这两个序列的元素可以来自不同类型的容器。第一个序列可能存于一个vector,第二个序列可能保存于一个list、deque、内置数组或其他容器中。两个序列中的算法也不完全匹配,但算法要求的知识能够比较两个序列中的元素。

当操作两个序列的算法要求比较两个序列中的元素时,比如equal算法,接受三个迭代器,前两个表示第一个序列迭代器的范围,第三个表示第二个迭代器的首元素。
上述用单一迭代器表示第二序列的算法都假定第二序列至少比第一序列长。若比第一个短,则造成第二序列中末尾之后(不存在)的元素和第一序列比较。确保算法不会试图访问第二序列不存在的元素是程序员的责任。

2.1.1 算法不检查写操作

fill_n算法

vector<int> vec;	//空向量
// 灾难;修改vec中的10个(不存在)元素
fill_n(vec.begin(), 10, 0);		

这个调用是一场灾难,指定写入10个元素,但vec中并没有元素–他是空的。
因此向目的位置迭代器写入数据的算法假定目的的位置足够大,能容纳要写入的元素。

2.1.2 back_inserter(插入迭代器)

头文件:iterator
属性 :迭代器、算法
作用:向容器中添加元素
优点:能保证算法有足够元素空间来容纳输入数据
运行原理:back_inserter接受一个指向容器的引用,返回一个于该容器绑定的插入迭代器。通过迭代器赋值时,赋值运算符通过调用push_back将一个具有定值的元素添加到容器中(注意不是算法添加,而是调用的push_back)。
例子

vector<int> vec;	//空向量
// 正确:back_inserter创建一个插入迭代器,可用来向vec添加元素
fill_n(back_inserter(vec) ,10, 0); //添加10个元素到vec

2.1.3 拷贝算法

拷贝并保存在输入序列末尾

copy算法:
作用:向目的位置迭代器 指向的 输入序列中的元素 写入数据
组成:接受三个迭代器,前两个表示一个输入范围,第三个表示目的序列的起始位置。
注意事项:传递给copy的目的序列至少要包含与输入序列一样多的元素。
例子

int a1[ ] = {0, 1, 2, 3, 4, 5 , 6, 7, 8 ,9 };
int a2[ ] = {sizeof(a1) / sizeof(*a1)}; // a2与a1大小一样(即注意事项)
// 拷贝的最后 ret指向了a2的尾元素之后的位置
auto ret = copy(begin(a1), end(a1), a2); //把a1的内容拷贝给a2
拷贝并创建新的序列

replace算法
作用:读取一个序列,并将其中所有等于给定值的元素都改为另一个值
组成:接受4个参数。前俩个是迭代器,表示输入序列,后两个是要搜索的值,另一个是新值。它将所有等于第一个值的元素替换成第二个值。
例子

// 将所有值为0的元素改为42
replace(list.begin(), list.end(), 0, 42);

若想保留原序列不变,可以调用replace_copy算法,此算法接受第三个迭代器参数。
例子:

//使用back_inserter按需要增长目标序列
replace_copy(list.cbegin(), ilst.cend(), 
						back_inserter(ivec), 0, 42);

调用之后,ilst并未改变,ivec是ilst的一份拷贝,只是其中的0变成了42。

2.2 重排容器元素的算法

该类算法的作用是:将容器中的元素重新排序。
sort算法:用法详细可参考c+±algorithm 头文件排序sort
作用:可以对类,结构体等元素进行排序。
原理:利用元素类型的”<“运算符实现排序。
例子:

假定有一个vector,保存了多个故事的文本,现在要简化,,使每个单词只出现一次,而不管单词在文档中出现多少次。
简单故事输入为: the quick red fox jumpe over the slow red turtle

为了消除多余的元素采用了以下策略:
①利用sort算法进行整体排序,生成的顺序如下:

foxjumpsoverquickredredslowthetheturtle

②利用unique算法使得相邻重复项调整,使其多余项置于容器“末端”,故返回一个指向不重复值范围末尾的迭代器,end_unique指向最后一个不重复元素之后的位置。生成顺序为:

foxjumpsoverquickredslowtheturtle??????

③利用erase函数删除多余元素,范围为(end_unique, words.end())。

程序为

void elimDups(vector<string> &words)
{
	//按字典序排序words,以便查找重复单词
	sort(words.begin(), words.end());
	
	//unique重新输入范围,使得每一个单词只出现一次
	//排列在范围的前部,返回指向不重复区域之后一个位置的迭代器
	auto end_unique = unique(words.begin(), words.end());
	
	//使用向量操作erase删除重复单词
	words.erase(end_unique, words.end());
}

注:本文主要来源于c++primer第五版

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值