迭代器令算法不依赖于容器,但算法依赖于元素类型的操作。
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被替换成了4210.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; //打印42lambda不能有默认参数,因此,一个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,' '));//传递ostream10.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());//123410.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));//记得先sort10.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