C++学习之泛型算法概述--摘自C++primer4

本文主要讨论C++标准库中的泛型算法(generic algorithm)。泛型算法是使用容器的强有力的辅助工具。
   如果文中有错误或遗漏之处,敬请指出,谢谢!
   标准库为容器类型定义的操作很少,并没有为每个容器实现更多的操作。因为这部分操作可以抽象出来为所有的容器工作,那就是泛型算法。所谓“泛型”是指这些算法可以应用于多种容器类型上,而容器内的元素类型也可以多样化。标准库提供了100多个泛型算法,主要定义于头文件<algorithm>中,还有一组泛化的算术算法定义于头文件<numeric>中。
 
   大多数泛型算法是工作于容器的一对迭代器所标识的范围,并完全通过迭代器来实现其功能。这段由迭代器指定的范围称为“输入范围”。带有输入范围参数的算法总是使用前两个参数标记该范围,分别指向要处理的第一个元素和最后一个元素的下一个位置。
 
   这些算法一般可划分为只读算法、改写元素算法或对元素重新排序算法,下面分别叙述之。
 


只读算法
 
find算法
   template<class InIt, class T>
      InIt find(InIt first, InIt last, const T& val);
 
   查询迭代器指定范围[first, last)范围内是否有val值。如果有,则返回该值对应的迭代器;否则,返回last表示查找失败。
 
accumulate算法
   template<class InIt, class T>
      T accumulate(InIt first, InIt last, T val);
   template<class InIt, class T, class Pred>
      T accumulate(InIt first, InIt last, T val, Pred pr);
 
   累加迭代器指定范围[first, last)范围内所有元素,再加上累加的初值val,返回累加的结果。第二个函数自定义操作:val = pr(val, *it)。
 注:用于指定累加起始值的第三个参数是必要的,因为算法对将要累加的元素类型一无所知,没有别的办法创建合适的起始值或者关联的类型。
 
find_first_of算法
   template<class FwdIt1, class FwdIt2>
      FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2);
   template<class FwdIt1, class FwdIt2, class Pred>
      FwdIt1 find_first_of(FwdIt1 first1, FwdIt1 last1, FwdIt2 first2, FwdIt2 last2, Pred pr);
 
   查询第一段范围内与第二段范围内任意元素匹配的元素的位置。如果找到,返回该元素对应的迭代器;否则,返回last1。第二个函数使用判断:pr(*it1, *it2)来代替第一个函数中的判断:*it1 == *it2。
 

写容器元素的算法
   在使用写元素的算法时,必须确保算法所写的序列至少足以存储要写入的元素。有些算法直接将数据写入到输入序列,另外一些则带有一个额外的迭代器参数指定写入目标。这类算法将目标迭代器用作输出的位置。还有第三种算法将指定数目的元素写入某个序列。
 
写入输入序列的元素
 
   写入到输入序列的算法本质上是案例的,因为只会写入与指定输入范围数量相同的元素。如fill算法:
   template<class FwdIt, class T>
      void fill(FwdIt first, FwdIt last, const T& x);
这个算法将指定范围内的每个元素都设定为给定的值。如果输入范围有效,则可以安全写入。这个算法只会对输入范围内已存在的元素进行写入操作。
 
不检查写入操作的算法
 
   这类算法如fill_n算法:
   template<class OutIt, class Size, class T>
      void fill_n(OutIt first, Size n, const T& x);
 
该算法从迭代器指向的元素开始,将指定数量的元素设置为给定的值。如果目标范围内的某些元素不存在,则该操作未定义。如下面的代码将发生不可预料的结果:
   vector<int> vec;              // empty vector
   fill_n(vec.begin(), 10, 0);   // disaster behavior
 
 注:对指定数目的元素做写入运算,或者写到目标迭代的算法,都不检查目标的大小是否足以存储要写入的元素。
  
back_inserter
 
   确保算法有足够的元素存储输出数据的一种方法是使用插入迭代器(insert iterator)。插入迭代器是可以给基础容器添加元素的迭代器。通常,用迭代器给容器元素赋值时,被赋值的是迭代器所指向的元素。而使用插入迭代器赋值时,则会在容器中添加一个新元素,其值等于赋值运算的右操作数的值。
 
   back_inserter函数是迭代器适配器,其使用一个对象作为实参,并生成一个适应其实参行为的新对象。比如,在下例中,传递给back_inserter的实参是一个容器的引用。back_inserter生成一个绑定在该容器上的插入迭代器。在试图通过这个迭代器给元素赋值时,赋值运算将调用push_back在容器中添加一个具有指定值的元素。因此,用back_inserter改写上面的代码可以有效地工作:
   vector<int> vec;                     // empty vector
   fill_n(back_inserter(vec), 10, 0);   // ok: appends 10 elements to vec
 
写入到目标迭代器的算法
 
   第三类算法向目标迭代器写入未知个数的元素。这类算法最简单的如copy算法:
   template<class InIt, class OutIt>
      OutIt copy(InIt first, InIt last, OutIt x);
 
copy算法带有三个迭代器参数:前两个指定输入范围,第三个指向目标序列的第一个元素。
 
算法的_copy版本
 
   有些算法提供所谓的“_copy”版本。这些算法对输入序列的元素做处理,但不修改原来的元素,而是创建一个新序列存储元素的处理结果。
 
   例如,replace算法:
   template<caass FwdIt, class T>
      void replace(FwdIt first, FwdIt last, const T& vold, const T& vnew);

该算法指定范围[first, last)内的所有元素值为vold替换为vnew。
 
   如果不想改变原序列,可以用replace_copy算法:
   template<class InIt, class OutIt, class T>
      OutIt replace_copy(InIt first, InIt last, OutIt x, const T& vold, const T& vnew);
 
这个算法接受第三个迭代器参数,指定保存替换后的序列的目标位置。例如:
   vector<int> vec;
   replace(ilist.begin(), ilist.end(), back_inserter(ivec), 1, 10);
调用该函数后,ilist没有改变,而ivec存储ilist的一份替换后的副本。
 

对容器元素重新排序的算法
sort算法
 
   这里只介绍sort和stable_sort这个类排序算法:
   template<class RanIt>
      void sort(RanIt first, RanIt last);
   template<class RanIt, class Pred>
      void sort(RanIt first, RanIt last, Pred pr);
   template<class RanIt>
      void stable_sort(RanIt first, RanIt last);
   template<class RanIt, class Pred>
      void stable_sort(RanIt first, RanIt last, Pred pr);
 
sort排序算法是最一般的类型,而stable_sort排序算法是稳定排序。
 
unique和unique_copy
 
   unique函数“删除”指定范围内的重复元素。注意:这里的“删除”不是真正意义上的删除,只是在有重复元素时,把后面的元素向前移动覆盖了原来的元素。函数返回的迭代器指向无重复元素序列最后一个元素的下一个位置。而unique_copy是它的“_copy”版本,返回的是生成的序列的最后一个元素的下一个位置。
   template<class FwdIt>
      FwdIt unique(FwdIt first, FwdIt last);
   template<class FwdIt, class Pred>
      FwdIt unique(FwdIt first, FwdIt last, Pred pr);
   template<class InIt, class OutIt>
      OutIt unique_copy(InIt first, InIt last, OutIt x);
   template<class InIt, class OutIt, class Pred>
      OutIt unique_copy(InIt first, InIt last, OutIt x, Pred pr);
 
注意:unique调用后,原序列的前面部分是无重复元素的序列,而后半部分是剩下没有被覆盖的序列。这里,需要手动删除后面的元素序列,范围由返回的迭代器和容器末端决定。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值