首页 > 代码库 > 【足迹C++primer】31、初识泛型算法

【足迹C++primer】31、初识泛型算法

初识泛型算法

理解算法的最基本方法是了解他们是否读取元素、改变元素或是重排元素顺序!

只读算法

#include<iostream>
#include<numeric>

using namespace std;

//对vec中的元素求和,初值是0
int sum=accumulate(vec.cbegin(), vec.cend(), 0);

这里面第三个参数决定了函数使用哪个加法运算符以及返回值类型。

算法和元素类型

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

这里有一个问题,就是后面stiring("")为什么要这样创建一个字符串呢?
string sum=accumulate(v.cbegin(), v.cend(), "");

这样看起来是对的,其实是有问题的。
//错误:const char*上没有定义“+”运算符
string sum=accumulate(v.cbegin(), v.cend(), "");

原因就是:如果我们传递一个字符串字面值,用于保存和的对象的类型将会是const char*。可是const char* 是没有“+”运算符的

操作两个序列的算法

//roster2中的元素数目应该至少与roster1一样多
equal(roster1.cbegin(), roster.cend(), roster2.begin());

三个参数,都是迭代器,前两个和上面一样表示范围,后一个表示第二个序列的开始。

由于equal调用迭代器完成的,所以我们可以通过调用equal来比较两个不同类型的容器中的元素。

要求!!!!第二个序列至少和第一个一样长

写容器元素的算法

一些算法会自己向输入范围书写元素。
如:
fill(vec.begin(), vec.end(), 0);    //将每一个元素重置为0
//将容器的一个子序列设置为10
fill(vec.begin(), vec.begin()+vec.size()/2, 10);

算法不检查写操作

vector<int> vec;    //空vector
//使用vec,赋予它不同值
fill_n(vec.begin(), vec.size(), 0);     //将所有元素重置为0
//函数fill_n假定写入指定个元素是安全的。
fill_n(dest, n, val)


这里有一个很容易犯的问题,在空容器上调用fill_n

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

介绍back_inserter

这个是插入迭代器!!!插入!!!插入!!插入!恩大笑就是插入元素的意思。

这个玩意是定义在iterator头文件中的一个函数!

vector<int> vec;    //空向量
auto it=back_inserter(vec); //通过它赋值会将元素插入到vec中!!
*it=42; //ok现在vec中有一个叫42的值了!!!

//我们常用back_inserter来创建一个迭代器,作为算法的目的位置来使用
vector<int> vec;    //空向量
//正确:back_inserter创建一个插入迭代器,可用来向vec添加元素
fill_n(back_inserter(vec), 10, 0);
//这里由于每次调用都会用到back_inserter返回的是push_back
//最终这个语句向vec的末尾添加了10个为0的元素

拷贝算法

三个参数!!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
看到序列那个不顺眼,就叫replace爸爸把它换了吧!!!

//将所有的0换成42
replace(ilst.begin(), ilst.end(), 0, 42);
//如果希望还是保留原来的序列,来一个新序列保存修改后的数据
//那么这里还有一个好玩意
replace_copy(ilst.cbegin(), ilst.cend(), back_inserter(ivec), 0, 42);
//调用后ilst没有改变,ivec包含ilst的一份拷贝,不过原来在ilst中值为0的元素ivec
//中都变成42

恩,从这里可以得到一个结论:
很重要!!!
是的!
那就是编书的那个家伙特别喜欢42这个数字,不知道是不是那家伙的幸运数字啊,但是特么有点大了,我们的幸运数字不都是0到9的吗!!!!

重排容器元素的算法

那就是!!
又来了,好吧就是:sort会重排输入序列中的元素是利用“<”来实现的;

消除重复元素

//好的 ,看个使用sort的案例
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());
}

sort就理解为从小到大排序吧,大笑简单好记易得分,就像高中数学,字大,空多,题少,嘿嘿!!
就是不会做大哭

使用unique

这个会消除相邻的重复项,返回不重复值范围末尾的迭代器。


PS:今天时间比较充足,所以就比较轻松,希望大家喜欢!!!
这里补充一句,要好好树立自己的目标,目标要时刻提醒自己,不能走着走着就迷路了,计划要明确,不然无处下牙,慢慢培养自己,每日三省吾身!!!