C++ primer读书笔记 10.1~10.2 初识泛型算法

泛型算法

  1. 独立于特定的容器
  2. 和迭代器的联系非常紧密
  3. 并不直接操作容器

上面三条一定要理解!

从三方面去理解泛型算法:

 泛型算法可以大致分为三类:只读、可写、重排。这一小节的用意就是针对每一类泛型算法介绍几个典型的函数,因为每一类算法在结构上都是相似的。

只读

这种算法只会读取给定范围内的元素

accumulate

定义在numeric头文件中,用于求和

int sum = accumulate(vec.begin(), vec.end(), 0);

算法的前两个参数用于表示一个迭代器范围,第3个参数表示求和的初始值。

返回值是迭代器范围内元素的和(以第三个参数为初始值)

第三个参数的类型特别重要,因为算法并不知道元素的类型,所以它会根据第3个参数的类型来推断使用哪种加法。

比如下面的调用就是错误的

string sum = accumulate(v.cbegin(), v.cend(), "");

表面上看第三个参数是一个string,但实际会被看作是一个字符数组,所以第3个参数的类型是const char*,由于const char*没有加法运算,所以调用是错误的

正确的写法是

string sum = accumulate(v.cbegin(), v.ceng(), string(""));

equal

作用于两个序列,它将第一个序列中的元素与第二个序列中的对应元素进行比较。

bool bIsEqual = equal(v1.cbegin(), v1.cend(), v2.cbegin());

它只接受三个参数,并没有指定第二个容器的结尾位置,这就要求第二个容器至少和第一个容器一样长,否则算法会发生错误。

这里并不要求两个容器的元素类型相同,只要能使用比较运算符==就可以了。

比如vector<string>和list<const char*>

操作两个序列的算法还有另外一种形式,就是传递四个参数,分别代码两个迭代器范围。

写算法

更新容器中元素的值。算法不会执行容器操作,因此不会改变容器的大小。

要求我们输入的范围不能比容器的范围大,这一点同样需要程序员自己来保证。

fill和fill_n

将给定的值赋予输入范围内的元素

fill(v.begin(), v.end(), 0);  
fill(v.begin(), v.begin() + v.size()/2, 10);

fill_n只接受一个迭代器

fill_n(iter, n, val);

将从iter开始的n个元素赋值为val

要知道泛型算法并不操作容器

vector<int> vec;  
fill_n(vec.begin(), 10, 0);

这个调用是错误的,fill_n并不是向容器中插入元素,它只负责更新元素的值

想要在空容器上使用fill_n也是有方法的,需要借助插入迭代器 : back_inserter

vector<int> vec;  
auto it = back_inserter(vec);  
*it = 42;

back_inserter的参数是容器的引用,返回值是一个特殊的迭代器

vector<int> vec;  
fill_n(back_inserter(vec), 10, 0);

这个调用是合法的,因为back_inserter返回的一个特殊的迭代器,它会执行push_back操作。

PS: 推测这个特殊迭代器的递增操作也是在执行push_back

copy

类似于equal,copy也接受三个迭代器,长度同样需要由程序员来保证。

int a1[] = {0,1,2,3};  
int a2[sizeof(a1)/sizeof(*a1)];  
auto ret = copy(begin(a1), end(a1), a2);

ret指向a2的尾后位置

replace

replace(v.begin(), v.end(), 0, 42);

将指定范围内的所有0替换为42

replace_copy

replace_copy(v1.begin(), v1.end(), back_inserter(v2), 0, 42);

将replace后的容器拷贝一份到v2中

重排元素

sort

将指定范围内的元素重排,它是利用元素类型的<运算符来实现排序的

sort(v.begin(), v.end());

unique

很容易把unique理解为“去重”, 这是不正确的。unique实际也只是执行重排的操作,并不包含“去”的过程(即不会删除元素,算法不会改变容器大小)

auto itr1 = unique(v.begin(), v.end());

unique会重排元素,容器中和其他元素重复的元素会被排到后面。

itr1是一个迭代器,itr1之前的元素都是不重复的,因为unique把和其他元素重复的那些内容挪到了itr1之后

我们可以用erase操作来删除这些元素,这个才是真正意义上的“去重”

v.erase(itr1, v.end());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值