c++Primer第十章:泛型算法(包含各种迭代器)

算法概览

一般都在algorithm,或者

算法使用
auto r = find(begin,end,val)val:要查找的值,找不到返回end()
auto sum = accumulate(begin,end,0)0是初始值,可以换为string("");
equal(L1.begin,L1.end,L2.begin)L2中的元素数目>=L1中元素数目,L1与L2做比较,如果全部相等就true,位置必须一一对应,逆序不行
fill(vec.begin,vec.end,0)填充初始值,0可以修改,但是初始不可为空
fill_n(l.begin,n,0)明确填充数量,l的大小
vector< int > vec fill_n(back_insert(vec),n,0)插入迭代器,赋值后都会自动调用push_back
auto ret = cpoy(l1.begin,l1.end,l2)注意l2的大小,返回最后一个插入元素之后的位置,即当l1.size()=l2.size(),ret是l2的尾元素之后的位置
repalce(l.begin,l.end,0,42)所有等于0的值换成42
repalce_copy(l.begin,l.end,back_insert(vec),0,42)vec是调整后序列的保存位置,保留了原序列
sort(begin,end)排序
auto end_unique = unique(words.begin,words.end)需要先进行排序,返回不重复范围末尾的迭代器,不会真正的删除元素,可以使用earse按照ret进行删除
stable_sort(begin,end,isShorter)相同长度的元素按照字典序
auto it = find_if(begin,end,谓词)返回第一个使谓词为真的元素,如果不存在,返回尾迭代器
for_each(begin,end,操作)访问每个数据,并进行操作,具体看下面
remove_if(begin,end,谓词)删除
remove_copy_if(v1.begin,v1.end,back_inserter(v2),谓词)v1不变,v2中都是使谓词为false的值
lst.merge(lst2)
lst.merge(lst2,comp)
lst.remove(val)会删除指定元素
lst.remove(一元谓词)
lst.reverse()
lst.sort()
lst.sort(comp)
lst.unique()会删除指定元素
lst.unique(pred)二元谓词
lst.splice ( iterator position, list<T,Allocator>& x );将所有的数据移向指定位置之前。_after是之后
void splice ( iterator position, list<T,Allocator>& x, iterator it );将 list x 中的由迭代器it指向的元素移到position处。_after是it之后的元素
void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last );将 list x 中的从迭代器 first 到迭代器 last 这一段元素移动到position处

定制

谓词

二元谓词

bool isShorter(const string &s1,const string &s2){
	return s1.size()>s2.size();
}

lambda表达式

格式

[捕获参数] (参数列表) ->返回值类型 {函数体}
可以忽略参数列表和返回值类型,但是捕获参数和函数体不能省略

auto f = []{return 42;}

重写isShorter函数

[] (const string &s1,const string &s2){return a.size()<b.size();}

使用表达式

stable_sort(begin,end,[] (const string &s1,const string &s2){return a.size()<b.size();})

捕获列表

lambda 只有在其捕获列表中捕获它所在函数中的局部变量,才能在函数体中使用该变量。但是可以直接使用局部静态变量

[sz] (const string &s) {return s.size()>sz;}

for_each算法
打印数据每个数据后面跟一个空格

for_each(begin,end,[](const strong &s){cout<<s<<" ";});

整合的代码


void elimDups(vector<string> &words){
	stable_sort(words.begin(),words.end(),[](const string &s1,const string &s2){return s1.size()<s2.size();});
	auto end_unique = unique(words.begin(),words.end());
	// while(end_unique!=words.end()){
	// 	end_unique = words.erase(end_unique);
	// 	end_unique++;
	// }
	words.erase(end_unique,words.end());
}

void biggies(vector<string> &words,vector<string>::size_type sz){
	elimDups(words);
	auto wc = find_if(words.begin(),words.end(),[sz](const string &s){return s.size()>sz;});
	auto count = words.end() - wc;
	cout<<"count="<<count<<endl;
	for_each(wc,words.end(),[](const string &s){cout<<s<<" ";});
	cout<<endl;
}

vector<string> vs{"sadsad","daddv","sa","rffdsvfegt","sda","addvgwe","dsadsadas","q","sadsad","daddv","sa","rffdsvfegt"};
biggies(vs,5);

结果
在这里插入图片描述

  1. 值捕获
    在lambda表达式创建时创建拷贝
int v=41;
auto f = [v1]{return v1};
v1=10;
auto j = f();//j=41

2.引用捕获

int v=41;
auto f = [&v1]{return v1};
v1=10;
auto j = f();//j=10

ostream流只能使用引用捕获

ostream &os=cout;
for_each(words.begin(),words.end(),[&os,c](const string &c){os<<s<<c;});

3.隐式捕获

[&,identifier_list],identifier_list是值捕获
[=,identifier_list],identifier_list是引用捕获

4.修改捕获的值
效果和刚刚一样,外部值改变不影响表达式;

v=42
[v] () mutable {return ++v;}
v=0;
调用之后v=43

外部值改变会影响表达式

[&v] () mutable {return ++v;}
v=0;
调用之后值为1;

5.注意lambda表达式的返回值,条件运算符不用操心。

参数绑定

格式

bind只能拷贝参数

auto newCallable = bind(callable,arg_list);

使用案例
_1表示占位符

auto check6 = bind(check_size,_1,6);
string s="hello";
bool b = check6(s);
//就不需要值捕获了
auto wc = find_if(words.begin(),words.end(),bind(check_size,_1,sz));

重排参数顺序
从小到大->从大到小

bool isShorter(const string &s1,const string &s2)
{...}
sort(begin,end,bind(isShorter(_2,_1)))

bind捕获os,使用ref,传递一个对象但是不拷贝

for_each(words.bigen(),words.end(),bind(print,ref(os),-1,' '));

插入迭代器

项目Value
back_inserter创建一个使用push_back的迭代器
front_inserter创建一个使用push_front的迭代器
inserter插入给定元素之前

代码

it = c.insert(it,val);
++it;指向原来的元素
list<int> l1{1,2,3,4};
list<int> lst2,lst3;
copy(l1.cbegin(),l1.cend(),front_inserter(lst2));
//st2={4,3,2,1};
copy(l1.cbegin(),l1.cend(),inserter(lst3,lst3.begin()));
//lst3={1,2,3,4};

iostream 迭代器

istream_iterator

项目Value
istream_iterator< T > in(is)in从输入流is读取类型为T的值
istream_iterator< T > end表尾后位置

使用流从标准输入读取数据

istream_iterator<int> in_it(cin);
istream_iterator<int> in_eof;
vector<int> vec;
while (in_it!=in_eof)
{
	vec.push_back(*in_it++);
}
for(auto e:vec)
	cout<<e<<" ";
cout<<endl;
//vector<int> vec(in_iter,eof)

结果
在这里插入图片描述

使用流读取文件

vector<string> vec_str;
cout<<"start"<<endl;
ifstream  input ("text.txt");
istream_iterator<string> str_it(input);
if(!input){
	cout<<"no such file"<<endl;
	return 0;
}
istream_iterator<string> str_eof;
cout<<*str_it<<endl;
while(str_it!=str_eof){
	vec_str.push_back(*str_it++);
}
cout<<vec_str.size()<<endl;
for(auto e: vec_str){
	cout<<e<<" ";
}
cout<<endl;
if(input.is_open()){
	cout<<"close file"<<endl;
	input.close();
}

结果
在这里插入图片描述

ostream_iterator

项目Value
ostream_iterator< T > out(os)out将值写到输出流os
ostream_iterator< T > out(os,d)out将值写到输出流os,每个值后面带个d
out = val使用<<运算符将val写入到out所绑定的ostream中

代码

	vector<string> vs{"sadsad","daddv","sa","rffdsvfegt","sda","addvgwe","dsadsadas","q","sadsad","daddv","sa","rffdsvfegt"};
	ostream_iterator<string> out_iter(cout," ");
	for(auto e:vs){
		*out_iter = e;
		out_iter++;
	}

结果
在这里插入图片描述
使用流处理类类型
不知道怎么回事out_iter有问题,老是类型不匹配,有没有大佬可以看一下怎么回事吗

istream_iterator<sales_data> item_iter(cin),eof;
    ostream_iterator<sales_data> out_iter(cout," ");
    sales_data sum = *item_iter++;
    // while(item_iter!=eof){
    //     if(item_iter->isbn()==item_iter->isbn()){
    //         // sum = sum + *item_iter;
    //         // item_iter++;//读取下一条记录
    //         sum += *item_iter++; 
    //     }
    //     else{
    //         out_iter = sum;
    //         sum += *item_iter++; 
    //         // sum = *item_iter;
    //         // item_iter++;//读取下一条记录
    //     }
    // }
    //out_iter = sum;

反向迭代器

逆序

sort(v.rbegin(),v.rend());

使用.base转换反向迭代器为普通迭代器

auto rcomma = find(line.crbegin,line.crend(),',');
cout<<string(rcomma.base(),line.end());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值