迭代器令算法不依赖于容器,但算法依赖于元素类型的操作。
10.1
vector<int>vi;
int a;
while(cin>>a)
vi.push_back(a);
auto result=count(vi.cbegin(),vi.cend(),1);
cout<<result;
10.2
改写类型即可。
除少数例外,标准库算法都对一个范围内(第一个元素和尾后元素的迭代器)的元素进行操作。大多数算法遍历输入范围方式相似,但它们使用范围中元素的方式不同。要了解它们是否读取元素、改变元素或是重排元素顺序。
一些算法只会读取其输入范围内的元素,而不改变元素。
accumulate (定义在头文件numeric中),第三个参数是和的初值。
string sum=accumulate(v.cbegin(),v.cend(),string("")) // 将string元素连接
equal 第三个元素接受第二个序列的首元素。这种只接受单一迭代器表示第二个序列的算法,都假定第二个序列至少和第一个序列一样长。
10.3
vector<int>vi{1,2,3};
auto result=accumulate(vi.cbegin(),vi.cend(),0);
10.4
第三个参数决定函数中使用哪个加法运算符和返回值类型。将初值设定为0,表明返回值为int类型,使用之后,会将double转换为int,损失精度
10.5
经验证,一切正常,但是C风格字符串的比较最好还是利用strcmp().
一些算法将新值赋予序列中的元素,使用时必须确保序列大小至少不小于我们要求算法写入的元素数目。
vector<int>vec;
fill_n(back_inserter(vec),10,0); //添加10个元素到vec
replace_copy(ilst.cbegin(),ilst.cend(),back_inserter(ivec),0,42);
//ilst没变,ivec包含ivec的拷贝,且其中0被替换成了42
10.6
vector<int>vi{1,2,3};
fill_n(vi.begin(),3,0);
10.7
a. lst和vec之间的大小未保证相同.
b. reserve只预留了空间,该容器内还是没有元素。
10.8 这只是产生了一个插入迭代器,然后使用这个迭代器进行插入操作。并非算法本身改变大小。
sort(words.begin(),words.end());//按字典序排序,默认升序
auto end_unique=unique(words.begin(),words.end());//返回指向不重复元素末尾的迭代器
words.erase(end_unique,words.end());
10.9
#include
#include
#include
#include
#include
using namespace std;
void elimDups(vector
{
cout<<"排序前:";
for (const auto &a:s)
{
cout<<a<<" ";
}
cout<<endl<<"sort()排序后:";
sort(s.begin(),s.end());//sort排序
for (const auto &a:s)
{
cout<<a<<" ";
}
cout<<endl<<"unique()排序后:";
auto str = unique(s.begin(),s.end());//unique排序
for (const auto &a:s)
{
cout<<a<<" ";
}
cout<<endl<<"erase()操作后:";
s.erase(str,s.end());//erase()操作
for (const auto &a:s)
{
cout<<a<<" ";
}
}
int main(int argc, char**argv)
{
string a[9] = {"I","Like","Like","C++","very","very","much","SCUEC","NewThread"};
vector
elimDups(s);
return 0;
}
10.10 因为算法始终作用于迭代器,不会直接对容器操作。
谓词:是一个可调用的表达式,其返回结果是一个能用做条件的值。元素类型必须能转换为谓词的参数类型。
bool isShorter(const string &s1,const string &s2)
{
return s1.size()<s2.size();
}
sort(words.begin(),words.end(),isShorter);//按长度排序
stable_sort:可保持等长元素间的原有顺序
10.11 替换10.9例题参数即可。
10.12 编写谓词即可。
bool compareIsbn(Sales_data s1, Sales_data s2)
{
return s1.isbn().size() < s2.isbn().size();
}
10.13
bool comp(string &s1)
{return (s1.size() >= 5)}
bool func(string &s1)
{
auto it1=vec.begin();
auto it2=partition(vec.begin(),vec.end(),comp);
if(it1==it2) //若没有符合要求的,则此时返回的迭代器指向首部
return false;
else
{
for(;it1!=it2;++it1)
cout<<*it1<<" ";
return true;
}
}
可忽略参数列表和返回类型,但永远包含捕获列表和函数体
auto f = [] {return 42;}; //定义可调用对象f,它不接受参数,返回42
cout << f() << endl; //打印42
lambda不能有默认参数,因此,一个lambda调用的实参数目永远和实参数目相等。
stable_sort(words.begin(),words.end(),
[](const string &a,const string &b)
{return a.size()<b.size();});
/查找第一个长度大于sz的元素/
auto wc=find_if(words.begin(),words.end(),
sz
{return a.size()>sz;});//返回迭代器
for_each算法接受一个可调用对象,并对输入序列中每个元素调用此对象。
for_each(wc,words.end(),
[](const string &s) {cout<<s<<" ";});
10.14
[](int &a,int &b){cout<<a+b;};
10.15
[value](int a){return (value+a);};
10.16 参考示例biggies。
10.17
stable_sort(vec1.begin(),vec1.end(),
[](Sales_data s1, Sales_data s2)
{return s1.isbn().size() < s2.isbn().size();});
10.18
void biggies(vector<string> &s, vector<string>::size_type sz)
{
elimDups(s);//字典排序、删除重复
stable_sort(s.begin(),s.end(),
[](const string &a,const string &b)
{return a.size()<b.size();});//按长度排序
auto it1 = partition(s.begin(),s.end(),
[sz](const string &s){return s.size()<=sz;});
for (it1; it1 != s.end(); ++it1)
{
cout<<*it1<<" ";
}
}
10.19 换成stable_partition 即可
被捕获变量值是在lambda创建时拷贝,因此其后对其修改不会影响到lambda内对应的值。
当用引用捕获时修改值就能影响到lambda内对应值啦。但必须确保被引用对象在lambda执行时存在。
void fun(ostream &os=cout,char c=' ')
{
for_each(xxx,xxx,
[&os,c](const string &s)
{os<<s<<C;});
}
当混合使用显隐时,第一个必须是&或=,且方式不同(比如隐式用了引用,那么显示就得用传值)
如果希望改变一个被捕获的变量值,就必须在参数列表首加上关键字mutable,因此,可变lambda能省略参数列表。
auto f = [v1]() mutable {return ++v1};
当需要为一个lambda定义返回类型时,要用尾置返回类型!
transform(v.begin(),v.end(),v.begin(),
[](int i)->int
{if(i<0) return -i;else return i;};
10.20
count_if(vi.begin(),vi.end(),
[](const string &a) {a.size()>6;})
10.21
int v=42;
auto f = &v->bool{while (v>0) --v; return !v; } ;
bind定义在functional中,可将其看作一个函数适配器。
auto New可调用对象 =bind(调用对象,参数列表)
其中参数列表中可用占位符_n,表示占用第n个参数。定义在placeholders命名空间
bool check_size(const string &s,string::size_type sz)
{return s.size()>=sz;}
auto wc=find_if(words.begin(),words.end(),
bind(check_size,_1,sz);
bool b1=wc("hello"); //用定值6和占位的const string&调用check_size函数
可用bind重新安排对象中参数位置
auto g=bind(f,a,b,_2,c,_1);
g(x,y);//即f(a,b,y,c,x)
sort(xx,xx,bind(isShorter,_2,_1));//变成由长到短排序
若希望传递给bind一个对象而又不拷贝他,可用ref函数
ostream &print(ostream &os,const string &s,char c)
{return os<<s<<c};
for_each(xx,xx,bind(print,ref(os),_1,' '));//传递ostream
10.22
bool func(string &s,string::size()_type sz)
{
return s.size()<=sz;
}
count_if(vec1.begin(),vec1.end(),bind(func,_1,6));
10.23 可调用对象形参数+1(自己)
10.24
bool check_size(const string &s,string::size_type sz)
{return s.size()>sz;}
string::size_type length=xxstring.size();
auto wc=find_if(vi.begin(),vi.end(),
bind(check_size,_1,length);
10.25
auto it1 = partition(s.begin(),s.end(),
bind(check_size,_1,sz));
插入器是一种适配器,接受一个容器,生成一个迭代器,能实现向给定容器添加元素。
list<int> lst={1,2,3,4};
list<int> lst2,lst3;
copy(lst.cbegin(),lst.cend(),front_inserter(lst2);//4321
copy(lst.cbegin(),lst.cend(),inserter(lst3,lst3.begin());//1234
10.26
back_inserter:使用push_back;
front_inserter:使用push_front,每次总把元素插在首位置
inserter:接受第二个参数,参数是指向容器插入位置的迭代器。插在给定元素前面
10.27
sort(vec1.begin(),vec1.end());
unique_copy(vec1.cbegin(),vec1.cend(),back_inserter(vec2));
10.28 见上述示例代码。注意vector不支持push_front操作。
istream_iterator<int> in_iter(cin),eof;
vector<int> vec(in_iter,eof);//迭代器范围构造
vec.push_back(*in_iter++);//后置递增构造
istream_iterator<int> in(cin),eof;
cout<< accumulate(in,eof,0) <<endl;//使用算法操作六迭代器
ostream_iterator<int> out_iter(cout," ");
for(auto e:vec)
*out_iter++=e;//循环输出
copy(vec.begin(),vec.end(),out_iter);//更简单的循环输出
10.29
ifstream in1("1.txt");
istream_iterator<string> str(in1),end;
copy(str,end,back_inserter(vec1));
10.30
istream_iterator<int> str(in1),end;
ostream_iterator<int> out_iter(cout," ");
copy(str,end,back_inserter(vec1));
sort(vec1.begin(),vec1.end());
copy(vec1.begin(),vec1.end(),out_iter);
10.31
unique_copy(str,end,back_inserter(vec1));//记得先sort
10.32 我用的find_if。
istream_iterator<Sales_item> item_iter(cin),eof;
vector<Sales_item> vs(item_iter,eof);
sort( vs.begin(), vs.end(), compareIsbn );
auto currt=vs.begin();
auto temp=currt;
while(currt!=vs.end())
{
temp=find_if(vs.begin(),vs.end(),
[currt.isbn()](Sales_ietm b) {return (currt.isbn()!=b.isbn());});
cout<< acumulate(currt,temp,Sales_item())<< endl;
currt=temp;
}
10.33
ifstream in("1.txt");
istream_iterator<int> it1(in),end;
vector<int> vec1;
copy(it1,end,back_inserter(vec1));
ofstream out("2.txt");
ofstream out2("3.txt");
ostream_iterator<int> it2(out," ");
ostream_iterator<int> it3(out2,"\n");
for (auto it=vec1.begin();it!=vec1.end();++it)
{
if ((*it)%2 == 0)//偶数
it2=it;
else
it3 = it;
}
普通迭代器和反向迭代器的关系反映了左闭合区间。
10.34
for (auto it1 = v1.rbegin(); it1 != v1.rend() ; ++it1)
cout<<*it1<<" ";
10.35
for (auto it1 = v1.end(); it1 != v1.begin() ;--it1)
cout<<*(it1-1)<<" ";
10.36
find(list1.rbegin(),list1.rend(),0);
10.37
copy(vec1.rbegin()+3,vec1.rend()-2,back_inserter(list1));
10.38
输入迭代器:可以读取序列中的元素,只用于顺序访问,*it++必须有效
输出迭代器,看作是输入迭代器的补集,可写,只赋值一次
前向迭代器:单向,支持输入输出,只沿一个方向移动
双向迭代器:双向,支持读写,还支持递增递减运算符。
随机访问迭代器:基本支持所有功能。
10.39
list:双向迭代器。
vector:随机访问迭代器
10.40
copy的三个参数,第一二个数输入迭代器,第三个是输出迭代器
reverse:双向迭代器
unique是前向迭代器
10.41
(a):遍历beg到end,找到oldVal就用newVal替换
(b):遍历beg到end,找到满足pred条件的就用newVal替换
(c):遍历beg到end,找到oldVal就用newVal替换,并将其拷贝至dest
(d):遍历beg到end,找到满足pred条件的就用newVal替换,并将其拷贝至dest
10.42
list1.sort();
list1.unique();
2/26/2019 7:41:55 PM
原文:https://www.cnblogs.com/Just-LYK/p/10439569.html