C++学习整理(泛型算法)

泛型算法

1、算法一般情况下,不直接操作容器,而是遍历由两个迭代器指定的一个元素范围来进行操作。

//find返回第二个参数表示收索失败
int val = 42;
auto result = find(vec.begin(),vec.end(),val);
int a[] = {1,23,4,56,7,90};
int * result1 = find(begin(a),end(a),val);

2、只读算法:find、count、equal、accumulate(头文件numeric

  • accumulate
/////第三个参数类型决定了函数中使用哪种加法和返回值类型
int result = accumulate(vec.begin(),vec.end(),0);
string num = accumulate(v.cbegin(),v.cend(),string(""));
/////""为const char * 类型,没有定义+运算符,错误
string num2 = accumulate(v.cbegin(),v.cend(),"");

3、写容器的算法:fill,fill_n,back_inserter,copy,replace,replace_copy

  • fill
算法不会执行容器操作,因此它们自身不可能改变容器的大小;
fill(vec.begin(),vec.end(),0);
  • fill_n
vector<int> vec;
fill_n(vec.begin(),vec.end(),0);//所有元素重置为0
fill_n(dest,n,val);//dest指向一个元素,从dest开始的序列至少包含n个元素
在没有足够多的元素的vec中使用fill_n是错误的
vector<int> v;
fill_n(v,10,0);
  • back_inserter:插入迭代器,执行赋值运算时,会调用push_back将一个具体给定的值元素添加到容器中
///正确
vector<int> v;
fill_n(back_inserter(v),10,0)
  • replace、replace_copy
///注意两者的区别
replace(list.begin(),list.end(),0,42);
replace_copy(list.begin(),list.end(),back_inserter(vec),0,42);

4、重排容器算法:sort,unique

  • unique
///删除vstr中重复的元素
void deleteTheComWords(vector<string> &vstr){
  sort(vstr.begin(),vstr.end());
  //返回指向不重复区域之后一个位置的迭代器
  auto end_unique = unique(vstr.begin(),vstr.end());
  //标准库算法对迭代器而不是对容器进行操作,因此不能直接添加或删除元素
  vstr.erase(end_unique,vstr.end());
}

5、定制操作

  • 向算法传递函数(一般指谓词)
    sort具有操作版本接受第三个参数:二元谓词
  ///程序一
  bool bigger(int a,int b){
    return a > b;
  }
  int main()
  {
      vector<int> v = {1,5,3,6,4};

      ostream_iterator<int> out_iter(cout," ");
      copy(v.begin(),v.end(),out_iter);

      cout << endl;
      //sort(v.begin(),v.end());//从小到大
      sort(v.begin(),v.end(),bigger);//从大到小
      copy(v.begin(),v.end(),out_iter);
      return 0;
  }
  • lambda表达式(C++11)
    ①[捕获列表](参数列表) -> 返回值类型 {函数主体} (可以忽略参数列表和返回值)
  程序二
  //删除重复单词、排序打印vector中长度大于sz的元素
  void bigger(vector<string> &words,vector<string>::size_type sz){
      sort(words.begin(),words.end());
      auto end_unique = unique(words.begin(),words.end());
      words.erase(end_unique,words.end());
      //在按照长度稳定排序
      stable_sort(words.begin(),words.end(),[](const string &s1,const string $s2){return s1.size() < s2.size();});
      //获取满足大于sz的迭代器
      auto wc = find_if(words.begin(),words.end(),[sz](const string &s){return s.size() >= sz;});
      //打印结果
      for_each(wc,words.end(),[](const string &s){cout << s << " ";});
      cout << endl;
  }

*stable_sort算法:可维持相等元素的原有顺序;
*lambda表达式中的捕获列表只能用于局部非static变量(sz),可直接使用局部static变量
②捕获列表:

  程序三
  //值捕获方式:前提变量可拷贝;被捕获变量的值是在lambda创建时拷贝,而不是调用时拷贝
  void fun1(){
    int a = 42;
    auto f = [a]{return a;};
    a = 0;
    auto j = f();//j = 42;f保持了a的拷贝
  }
  //引用捕获方式:
  void fun2(){
    int a = 42;
    auto f = [&a]{return a;};
    a = 0;
    int j = f();//j为0
  }
  //隐式捕获:在捕获列表中使用=或&,表示值捕获和应用捕获
  void printbigger(vector<int> vec,int bigger,ostream &os = cout, char c = ' '){
    //隐式捕获os,显示捕获c
    for_each(vec.begin(),vec.end(),[&,c](const int & i){os << i << c;});
    for_each(vec.begin(),vec.end(),[=,&os](const int & i){os << i << c;});
  }
  //可变的lambda
  void fcn3(){
    int v1 = 42;
    auto f = [v1]() mutable {return ++v1;};
    v1 = 0;
    auto j = f();//j = 43
  }

③指定lambda的返回值

   程序四
  //返回一个条件表达式,编译器可以推断返回类型
  transform(v.begin(),v.end(),v.begin(),[](int i){return i < 0 ? -i:i;});
  //将会产生错误不能推断具体的返回类型
  transform(v.begin(),v.end(),v.begin(),[](int i){if (i < 0) return -i;else return i;});
  //正确
  transform(v.begin(),v.end(),v.begin(),
            [](int i) -> int
            {if (i < 0) return -i;else return i;});
  • 参数绑定(将多元谓词转化为一元谓词)
  ////程序5
  //二元谓词
  bool check_size(const string &s,string::size_type sz){
    return s.size() > sz;
  }
  auto check5 = bind(check_size,_1,5);//_1为占位符;using namespace std::placeholders;
  string s = "hello";
  bool b = check5(s);//=>check_size(s,5)

6、头文件iterator中的迭代器

  • 插入迭代器
  *back_inserter <==> push_back
  *front_inserter <==> push_front
  *inserter <==> 元素被插入到给定迭代器之前

  list<int> lst = {1,2,3,4};
  list<int> lst1,lst2;
  copy(lst.begin(),lst.end(),front_inserter(lst1));//4 3 2 1
  copy(lst.being(),lst.end(),inserter(lst2,lst2.begin()));//1 2 3 4

  程序6
  //将vector中不重复的元素copy到list中
  void v2l(vector<int> &v,list<int> &l){
    sort(v.begin(),v.end());
    unique_copy(v.begin(),v.end(),inserter(l,l.begin()));
  }

  int main()
  {
      vector<int> v = {1,5,3,6,4,5,8,2,3};
      list<int> l;
      v2l(v,l);
      ostream_iterator<int> out_iter(cout," ");
      copy(l.begin(),l.end(),out_iter);
      cout<<endl;
      return 0;
  }
  • 输入输出迭代器
    *输出迭代器(ostream_iterator)在程序6中使用过了
    *输入迭代器(istream_iterator)
  程序7
  void testistream_iter()
  {
      vector<int> vec;
      ostream_iterator<int> out_iter(cout," ");

      istream_iterator<int> in_iter(cin);

      istream_iterator<int> eof;//结束标志
      while (in_iter != eof)//输入非数字时结束
          vec.push_back(*in_iter++);
      copy(vec.begin(),vec.end(),out_iter);
  }

参考C++Primer

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值