版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C++程序设计宋存利第十二章标准模板库知识点容器顺序容器容器适配器关联容器STL迭代器迭代器的类型迭代器的类别迭代器失效问题算法标准模板库标准模板库(StandardTemplateLibrary,STL)是高效的程序库,是ANSI/ISO标准中最新的也是极具革命性的一部分。该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法,为广大程序员们提供了一个可扩展的应用框架,高度体现了软件的可复用性。STL的核心内容是容器(Container)、迭代器(Iterator)、算法(Algorithm),这三者协同工作,为各种编程问题提供了有效的解决方案。12.1容器STL定义了顺序容器、容器适配器和关联容器。容器类共享部分公共接口,只定义了少量操作,大多数操作由算法库提供。如果两个容器提供了相同的操作,则它们的接口(函数名和参数个数)相同。12.1.1顺序容器顺序容器(sequencecontainers)内的元素按其位置顺序存储和访问。顾名思义,这些元素是顺序存放的,元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。vector、deque、list都属于此类容器。vector:将元素置于一个动态数组中加以管理,可以随机存取元素(用索引直接存取),数组尾部添加或移除元素非常快速,但是在中部或头部安插元素比较费时。vector所在头文件为<vector>。deque:是“double-endedqueue”的缩写,对应数据结构的双向队列,可以随机存取元素(用索引直接存取),队列头部删除和尾部添加元素都非常快速,但是在中部或头部安插元素比较费时。deque所在头文件为<deque>。list:双向链表,不提供随机存取,在任何位置上执行插入或删除动作都非常迅速,内部只需调整一下指针。list所在头文件为<list>。12.1.1顺序容器——特征(1)vector和deque容器采用的是类似数组的连续存储,因此提供了对元素的快速访问,但付出的代价是在容器的任意位置插入或删除元素,比在容器尾部插入和删除的开销更大,因为要保证其连续存储,需要移动元素;(2)list容器的存储结构是链表结构,因此在任何位置都能快速插入和删除,但付出的代价是元素的随机访问开销较大。(3)deque容器提供了高效地在其首部insert和erase的操作,就像在尾部一样。在deque容器首部或尾部删除元素则只会使指向被删除元素的迭代器失效。在deque容器的任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器都失效。12.1.1顺序容器假设C为顺序容器vector、deque或list的模板类,则定义一个C类型的容器的语法如表所示:定义语法解释说明C<T>c;创建一个T型数据的空容器;适用于所有容器。C<T>c2(c);创建一个T型数据的容器c的副本,适用于所有容器。C<T>c(b,e);创建一个T型数据的容器,且用迭代器[b,e)范围内的元素构造容器,适用于所有容器。C<T>c(n);创建一个含有n个默认值的T型数据的容器,仅适用于顺序容器。(若T是类名,则T类中必须提供默认构造函数。)提示:在将一个容器复制到另一个容器时,类型必须匹配,即容器类型和元素类型必须相同。12.1.1顺序容器容器定义举例:(1)vector<double>c;//定义存放double型数据的空的vector容器c(2)inta[]={1,2,3,4,5,6,7,8,9,10};list<int>List(a,a+10);//定义存放int数据的列表,该列表以数组a的元素初始化12.1.1顺序容器-容器迭代器每种容器都定义了自己的迭代器类型,迭代器的作用相当于指针,利用迭代器可遍历容器中的元素。具体定义C类型容器的迭代器的语法为:C<T>::iteratoriter;\\iter为C类型容器迭代器每个容器都定义了begin和end函数,用于返回容器的第一个元素位置或最后一个元素的下一个位置。例如定义vector容器的迭代器:vector<int>c;//定义容器cvector<int>::iteratoriter=c.begin();//将迭代器iter指向容器c的第一个元素vector<int>::iteratoriter=c.end();//将迭代器iter指向容器c的最后一个元素之后提示:end并不指向容器的任何元素,而是指向容器的最后元素的下一位置,称为超出末端迭代器。如果vector为空,则begin返回的迭代器和end返回的迭代器相同。一旦像上面这样定义和初始化,就相当于把该迭代器和容器进行了某种关联,就像把一个指针初始化为指向某一空间地址一样。12.1.1顺序容器-容器迭代器迭代器的常用操作如表12.2所示:操作解释说明
*iter返回迭代器所指向的元素的引用
iter->mem对iter进行解引用,获取指向元素的指定成员
++iter给iter加1,使其指向容器中下一个元素
iter++
--iter给iter减1,使其指向容器中前一个元素
iter--
iter1==iter2当两个迭代器指向同一个容器时,判断他们是否指向同一元素,或者都指向同一个容器的超出末端的下一个位置
iter1!=iter2当两个迭代器指向同一个容器时,判断他们是否指向容器的不同元素。迭代器的案例;下面的程序段将容器List中的元素利用for循环设置为0:inta[]={1,2,3,4,5,6,7,8,9,10};list<int>List(a,a+10);
//定义容器并初始化list<int>::iteratorp;//定义迭代器//利用for循环将List中元素设置为0for(p=List.begin();p!=c.end();p++)*p=0;12.1.1顺序容器-const_iterator迭代器每种容器还定义了一种名为const_iterator类型的迭代器,该类型的迭代器只能读取容器中的元素,不能改变容器中的值,类似于指向常量的指针。而普通的迭代器即可对容器进行读操作也可进行写操作。例如可以进行如下操作:for(vector<int>::const_iteratoriter=c.begin();iter!=c.end();++iter)cout<<*iter<<endl;//合法,输出容器中元素值,读操作for(vector<int>::const_iteratoriter=c.begin();iter!=c.end();++iter)*iter=0;//不合法,不能对容器中的元素进行写操作12.1.1顺序容器-常用成员函数容器有一组公共的成员函数,它们的函数名、参数、函数功能完全相同,因此同学掌握了一种容器的函数的使用,其它容器也就基本掌握。下面将分类说明:(1)容器的起止位置函数,如表12.4所示:函数名解释说明begin()
返回指向容器中第一个元素的迭代器
end()
返回指向容器中最后一个元素的下一个位置的迭代器
rbegin()
返回指向容器中最后一个元素的逆序迭代器
rend()
返回指向容器中第一个元素前面的位置的逆序迭代器12.1.1顺序容器-常用成员函数(2)向容器中增加元素的函数,如表12.5所示:函数名解释说明push_back(t)
在容器的尾部添加值为t的元素,返回void类型
push_front(t)
在容器的前端添加值为t的元素,返回void类型
(提示:只适用于list和deque容器类型)
insert(p,t)
在迭代器p所指向的元素前面插入值为t的新元素,返回指向新元素的迭代器
insert(p,n,t)
在迭代器p所指向的元素前面插入n个值为t的新元素,返回void类型
insert(p,b,e)
在迭代器p所指向的元素前面插入迭代器范围[b,e)内的元素,返回void类型12.1.1顺序容器-常用成员函数(3)与容器大小有关的函数,如果12.6所示:函数名解释说明size()
返回容器中的元素个数,返回类型为C::size_type
max_size()
返回容器可容纳的最多元素个数,返回类型为C::size_type
empty()
如果容器为空,则返回true,否则返回false
resize(n)
调整容器的长度大小,使其能容纳n个元素,新增元素采用默认值初始化
resize(n,t)
调整容器的长度大小,使其能容纳n个元素,所有新增元素值为t12.1.1顺序容器-常用成员函数(4)访问容器中元素的函数,如表12.7所示:函数名解释说明
back()
返回容器的最后一个元素的引用。如果容器为空,则该操作未定义
front()
返回容器的第一个元素的引用。如果容器为空,则该操作未定义
c[n]
返回下标为n的元素的引用;如果n<0orn>=size(),则该操作未定义提示:只适用于vector和deque容器,c为容器对象
at(n)
返回下标为n的元素的引用;如果下标无效,则抛出异常out_of_range异常提示:只适用于vector和deque容器12.1.1顺序容器-常用成员函数(5)删除元素函数,如表12.8所示:函数名解释说明erase(p)删除迭代器p所指向的元素。返回一个迭代器,它指向被删除的元素后面的元素。如果p指向容器内最后一个元素,则返回的迭代器指向容器的超出末端的下一个位置;如果p本身就是指向超出末端的下一个位置的迭代器,则该函数未定义erase(b,e)删除[b,e)内的所有元素。返回一个迭代器,它指向被删除元素段后面的元素。如果e本身就是指向超出末端的下一个位置的迭代器,则返回的迭代器也指向超出末端的下一个位置。clear()删除容器内的所有元素,返回voidpop_back()删除容器内的最后一个元素,返回void。如果容器为空,则该操作未定义。pop_front()删除容器内的第一个元素,返回void。如果c为空容器,则该操作未定义。
提示:只适用于list和deque容器12.1.1顺序容器-常用成员函数(6)赋值与交换操作,具体如表11.9所示:操作名称解释说明c1=c2
将c2的元素复制给c1。c1和c2的类型必须相同。c1中的元素将被全部删除c1.swap(c2)
交换内容:调用该函数后,c1中存放的是c2原来的元素,c2中存放的是c1原来的元素。c1和c2的类型必须相同。该函数的执行速度通常要比将c2的元素复制到c1的操作快。c.assign(b,e)
重新设置c的元素:将迭代器b和e标记的范围内所有的元素复制到c中。b和e必须不是指向c中元素的迭代器。c.assign(n,t)
将容器c重新设置为存储n个值为t的元素。12.1.1顺序容器-应用案例【例12-1】顺序容器应用案例,对vector容器操作的案例。Twelvth_1.cpp【例12-2】利用list容器解决的问题。Twelvth_2.cpp12.1.2容器适配器适配器(adaptor)是STL中的通用概念,包括容器适配器、迭代器适配器和函数适配器。本质上,适配器是使一事物的行为类似于另一事物的行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现,只是发生了接口转换而已。这就类似于我们手机充电的时候需要电源适配器来把220v的交流电转换成较低电压的直流电以供手机充电使用,220v的电压太高了,我们不需要那么高的电压,而且高电压还有可能产生其他很多不良后果。C++提供了三种容器适配器:stack(栈),queue(队列)和priority_queue(优先级队列)。默认的stack和queue基于deque实现,默认的priority_queue基于vector实现。12.1.2容器适配器每个适配器都定义了默认构造函数,用于创建空对象;一个带容器参数的构造函数,将参数容器的副本作为其基础值。下面以栈的创建为例,说明容器适配器的创建:stack<int>s;//采用默认构造函数创建一个空的栈对象s,基于deque实现stack<int,vector<int>>stk;//建立一个以vector实现的空栈list<double>values{1.414,3.14159265,2.71828};//创建一个list对象valuesstack<double,list<double>>my_stack(values);//建立一个以list实现的非空栈stack<double,list<double>>copy_my(my_stack);//12.1.2容器适配器-stackstack:stack定义在头文件<stack>中,他是一种后进先出的数据结构,其操作相比其底层的容器操作要少的多,具体栈的操作如表12.10所示:函数名解释说明top()返回一个栈顶元素的引用,类型为T&。如果栈为空,返回值未定义。push(constT&obj)压栈操作,将对象obj压入栈顶push(T&&obj)以移动对象的方式将对象压入栈顶。这是通过调用底层容器的有右值引用参数的push_back()函数完成的。pop()出栈,弹出栈顶元素。size()返回栈中元素的个数。empty()在栈中没有元素的情况下返回true,否则false。emplace()用传入的参数调用元素对象的构造函数,在栈顶生成对象。swap(stack<T>&other_stack)将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于stack对象有一个特例化的全局函数swap()可以使用。=可以将相同类型的栈对象进行赋值操作【例12-3】栈应用的例子stack有广泛的应用。例如,Word编辑器中的undo(撤销)机制就是用栈来记录连续的变化。撤销操作可以取消最后一个操作,这也是发生在栈顶部的操作。C++编译器使用栈来解析表达式,当然也可以用栈来记录C++代码的函数调用。Twelvth_3.cpp12.1.2容器适配器-queuequeue定义在<queue>头文件中,queue
队列也是一个线性存储结构,元素数据的插入在队尾进行,删除操作在队头,从而构成了一个先进先出FIFO(First
In
First
Out)的容器。队列的创建与栈stack类似,因此可参考前面栈的创建语句创建。队列的常用操作如表所示:函数名解释说明push(x)入队,将x插入到队列的末端。pop()出队,弹出队列的第一个元素。注意:并不会返回被弹出元素的值front()访问队首元素,例如:q.front(),即最早被压入队列的元素。back()访问队尾元素,例如:q.back(),即最后插入队列的元素。empty()判断队列空,例如:q.empty(),当队列空时,返回true,否则返回false。size()返回队列中的元素个数,如例:q.size()12.1.2容器适配器-priority_queuepriority_queue的头文件为<queue>,优先级队列容器与队列一样,只能从队尾插入元素,从队首删除元素。但是它有一个特性,就是队列中最大的元素总是位于队首,所以出队时,并非按照先进先出的原则进行,而是将当前队列中最大的元素出队。这点类似于给队列里的元素进行了由大到小的顺序排序。元素的比较规则默认按元素值由大到小进行,可以重载“<”操作符来重新定义比较规则。优先级队列可以用向量(vector)或双向队列(deque)来实现。其常用操作如表12.12所示。函数名解释说明push(x)入队,将x插入到队列的末端。pop()出队,弹出队列的第一个元素。注意:并不会返回被弹出元素的值top()访问队首元素。empty()判断队列空,当队列空时,返回true,否则返回false。size()返回队列中的元素个数,如例:q.size()12.1.2容器适配器-priority_queue【例12-4】优先级队列的创建语句如下:priority_queue<int>q;
//由大到小priority_queue<int,vector<int>,greater<int>>q;
//由小到大priority_queue<vector<int>,less<int>>pq1;
//由小到大
提示:greater<type>和less<type>是系统提供的模板函数,在头文件<functional>中定义,greater为大于函数,less为小于函数。【例12-5】程序案例,优先级队列的应用.twelvth_5【例12-5-2】另一个改变后的案例.twelvth_5_212.1.3关联容器
关联容器(associatedcontainers)的特点是元素位置按元素键值(key)排序确定,和插入顺序无关,因此元素在插入、删除和查找操作中有很大优势,时间复杂度可以达到log2N,支持通过键来高效的查找和读取元素,这是它和顺序容器最大的区别。
两种基本的关联容器是map和set,其中map的元素以键-值对(key-value)的形式组织,键用作元素在map中的索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效的支持关于某个键是否存在的查询。而multiset和multimap分别是set和map容器的扩展,区别是set和map容器的键唯一(即使插入了重复的值,它也只保留一个次),而multiset和multimap允许重复。由于这些容器中的元素要按照键值大小确定其存储位置,因此对于用户自定义数据类型,要定义这些类型的比较函数。提示:
提示:关联容器与顺序容器的本质区别在于:关联容器是通过键值存储和读取元素的,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。关联容器不提供front、push_front、pop_front、back、push_back和pop_back操作。12.1.3关联容器set/multiset使用set/multiset必须包含头文件<set>,set仅包含一个键,set内相同数值的元素只能出现一次,multiset可包含多个数值相同的元素。下面介绍set集合的常用操作如表12.13所示,该表中加粗的函数同样使用于map对象:函数名解释说明set<T>a;定义一个集合a,它可以存放T类型数据,a.begin()返回集合第一个元素的迭代器a.end()返回集合最后一个元素之后的迭代器a.clear()清除集合元素a.empty()判断集合是否为空a.size()返回集合的元素个数a.count(x)返回集合中原始x的个数,通常为0或1;对应于map对象,x为键值a.insert(x)插入元素x,对应于map对象,x为一个pair对象a.insert(b,e)插入迭代器区间[b,e)之间的元素a.erase(x)删除元素x;对应于map对象,x为键值a.erase(b,e)删除区间[b,e)之间的元素a.erase(iterator)删除迭代器iterator指定的元素a.lower_bound(x)返回第一个不小于元素x的迭代器;对应于map对象,x为键值a.upper_bound(x)返回最后一个大于元素x的迭代器;对应于map对象,x为键值a.find(x)若元素在集合中,则返回它的迭代器,否则返回结束迭代器;对应于map对象,x为键值12.1.3关联容器-set【例12-6】set集合案例,通过下面的应用,希望帮助同学理解集合set的操作。Twelvth_6
数学上,对集合常见的运算有并、交、差、和对称差等等。在STL中,提供了对集合进行相应运算的算法,它们所在的头文件为<algorithm>,算法为:set_union:该函数模板实现了集合的并集运算,它至少需要5个参数:两个迭代器用来指定左操作数的集合范围,另两个迭代器用来作为右操作数的集合范围,还有一个迭代器用来指向结果集合的存放位置。set_union注意:set_union函数需要参数集合以相同顺序事先排序。(1)set_union函数原型1:set_union(A.begin(),A.end(),B.begin(),B.end(),inserter(C1,C1.begin()));
它的功能是将集合A和集合B的元素求并集,并将结果插入到集合C1中。(2)set_union函数原型2:set_union(A.begin(),A.end(),B.begin(),B.end(),ostream_iterator<int>(cout,""));
它的功能是将集合A和集合B的元素求并集,并将结果通过流cout输出到显示器,元素之间用空格隔开。其中,ostream_iterator是输出流类的迭代器,在头文件<iterator>中。关于集合的其它算法set_intersection:求两个集合的交集,函数原型同set_unionset_symmetric_difference:求两个集合的对称差集,函数原型同set_unionset_difference:求两个集合的差集,函数原型同set_unionincludes:判断一个集合是否包含另一个集合,函数原型同set_union【例12-7】集合运算案例,该案例实现集合的并,交,差,包含等运算。Twelvth_7.cpp12.1.3关联容器map/multimap使用他们必须包含头文件<map>,map的元素是“键-值”对的二元组形式,键用作元素在map中的索引,而值则表示所存储和读取的数据,map内相同数值的元素只能出现一次。multimap内可包含多个数值相同的元素。创建map或multimap类型对象的语句一般格式为:map<键的类型,值的类型>map1;//键和值的类型可自由确定例如:map<int,string>students;//整型键,字符串值map<string,int>schools;//字符串键,整型值12.1.3关联容器map/multimap在介绍map的操作之前,首先介绍与之密切关联的一个标准库中提供的类pair,该类所在的头文件为<utility>,它有两个公有的数据成员first和second,map的每个元素就是一个pair对象,其中pair对象的创建可采用如下语句:
pair<T1,T2>p;该语句创建一个空的pair对象,它的数据成员first的类型为T1,second为T2或者:
pair<T1,T2>p<v1,v2>;该语句创建一个pair对象,它的数据成员first的类型为T1,second为T2,并且first的值为v1,second的值为v2。12.1.3关联容器map/multimapmake_pair模板函数的功能是返回一个pair对象,一般在用到pair对象的地方会经常用到此函数,其函数原型为:
pair<T1,T2>make_pair(T1v1,T2v2);用法举例:
pair<int,string>p;p=make_pair(1,"demo1");(1)map创建对象的语法有如下形式:
map<T1,T2>m;//创建一个名为m的空map对象,其键和值类型分别为T1和T2类型map<T1,T2>m(m2);//创建一个m2的副本m,m和m2必须要有相同的键和值类型map<T1,T2>m(b,e);/*创建map类型的对象m,存储迭代器b和e标记范围内所有元素的副本。元素的类型必须能转换为pair<constk,v>*/12.1.3关联容器map/multimap(2)map中插入元素利用下标方式向map对象中插入元素map<string,int>M;M[“tom”]=5;//插入元素
利用成员函数insert插入元素
M.insert(pair<string,int>("jerry",1));//或者是M.insert(make_pair("jerry",1));//或者M.insert(map<string,int>::value_type("peter",6));map容器其他操作参考set集合常用成员函数介绍12.1.3关联容器map/multimap【例12-8】对map或multimap容器操作的案例,该案例实现对map元素的添加、遍历和删除基本操作。Twelvth_8.cpp12.2STL迭代器
迭代器的意义类似于指针,STL中预定义的迭代器类型有iterator、const_iterator、reverse_iterator和const_reverse_iterator。每个一级容器都定义了这些迭代器类型。const_iterator和iterator类似,区别在于const_iterator迭代器不允许修改容器中元素的值,类似于前面第二章介绍的指向常量的指针。反向迭代器reverse_iterator是一种反向遍历容器的迭代器,也就是从容器的最后一个元素到第一个元素遍历容器。反向迭代器的自增(或自减)的含义反过来了,对于反向迭代器,++运算符将访问前一个元素,--运算符将访问下一个元素。12.2STL迭代器声明一个容器的迭代器的方法:
容器类型<元素类型>::iterator迭代器标识符;
例如:
vector<int>::iteratorp1;//p1是vector<int>类型的迭代器vector<int>::const_iteratorp2;//p2只能读vector<int>容器的元素,不可以修改vector<int>中的元素12.2STL迭代器
提示:C++11标准支持类型推测,使用的关键字是auto,在这里auto不是一个类型的“声明”,而是一个“占位符”,编译器在编译时会将auto替换为变量实际的类型。使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。使用auto来定义一个迭代器,其格式一般为:auto迭代器标识符=容器对象.begin();//rbegin()也行或者:
auto迭代器标识符=容器对象.end();//rend()也行【例12-9】迭代器应用案例,利用二分查找法查找容器中是否存在某元素。Twelvth_9.cpp【例12-10】反向迭代器的应用案例。Twelvth_10.cpp12.2.2迭代器的类别输入迭代器(InputIterator):用于从容器中读取元素,每一步只能向前方移动一个元素。输出迭代器(OutputIterator):用于向容器中写入元素,每一步只能向前方移动一个元素。向前迭代器(ForwardIterator):包含输入输出迭代器的所有功能,每一步只能向前方移动一个元素进行输入或输出双向迭代器(BidirectionalIterator):包含向前迭代器的所有功能,还有向后移动的能力,每一步都可自由选择向前移或向后移。随机访问迭代器(RandomAccessIterator):具有任意访问元素的能力,即可向前,也可向后,还可跳跃访问。
不同容器,由于其内存组织结构不同,因此支持的迭代器操作不同,详见书中介绍。12.2.3迭代器失效问题当向一个容器中插入或删除一个元素时,容器中元素的组织有可能发生变化,因此会使得相应的迭代器发生失效的问题,因此在编程时要注意避免。不同容器,元素在内存的组织不一样,因此发生失效的情况也不一样。1.对于顺序容器(如vector、deque),元素在内存的组织采用数组形式,即分配了连续的内存空间,删除当前的iterator会使后面所有元素的iterator都失效。这是因为删除一个元素导致后面所有的元素会向前移动一个位置。所以不能使用erase(iter++)的方式删除一个元素,否则迭代器iter将失效,还好erase方法可以返回下一个元素的有效迭代器。【例12-11】迭代器失效案例,该程序删除容器中大于3的元素值。Twelvth_11.cpp修订程序后再次运行程序Twelvth_11_1.cpp12.2.3迭代器失效问题提示:对于关联容器(如map,set,multimap,multiset),由于它们使用不连续的存储结构,因此删除当前迭代器iterator所指元素,仅仅会使当前的iterator失效,因此只要在erase时,递增当前iterator即可让其指向下一个元素,所以一般采用erase(iter++)的方式删除迭代器所指元素。【例12-12】实现set容器的erase操作,将set容器中大于3的元素删除,请将其与【例12-11】进行比较学习。Twelvth_12.cpp12.3算法STL为程序员提供了大约100多个可以用来对容器进行操作的函数模板。它不仅可用于系统提供的容器类型,而且适用于普通的C++数组或自定义的容器。学习和熟悉STL提供的算法,可以大大减轻程序员的编程负担,提高编程效率和编程质量。算法所在的头文件有<algorithm>、<numeric>和<functional>。<algorithm>是所有STL头文件中最大的一个,它是由一大堆函数模板组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。<numeric>体积很小,只包括几个在序列上面进行简单数学运算的函数模板,包括加法和乘法在序列上的一些操作。<functional>中则定义了一些模板类,用以声明函数对象。12.3算法STL算法命名时,引入了两种特殊的后缀:后缀_if:如果某算法有两种形式,其中一种有后缀_if,一种没有,且参数个数相同,则没有后缀的要求传入数值,有后缀_if的要求传入函数或函数对象(functionobject)。
例如:常用的查找函数find()用来查找具有某值的元素,而find_if()则查找满足某个准则函数或函数对象(functionobject)的第一个元素。但请注意,并非所有要求传递准则函数或functionobject的函数都有后缀_if。后缀_copy:表明区间中的元素不仅被操作,而且还会被复制到目标区间中。12.3算法STL中算法大致分为四类:非更易型算法:指不直接修改其所操作的容器元素值的算法。更易型算法:指可以修改所操作的容器元素的算法。移除型算法:去除不满足条件元素算法,但实际并不直接删除掉。变序型算法:将修改元素在区间的顺序。排序算法:对序列进行排序和合并的算法。已排序区间算法:在已排序区间上操作的算法要求其操作的容器有有序的,例如二分查找。数值算法:将对容器内容进行数值计算。12.3算法-非更易型算法相关函数介绍详解课本,几个常用函数的常用原型。for_each(begin,end,fun);for_each()遍历容器从起始位置begin到终止位置end之间的每个元素,并把元素对象作为回调函数fun的参数,由fun进行处理。其中,第一个参数是起始迭代器,第二个参数是终止迭代器,第三个参数是回调函数(回调函数的形参类型与容器中的元素类型一致)。count((begin,end,Tval);count函数统计容器从begin到end区间中值为val的元素的个数。find(begin,end,Tval);find函数在容器的begin到end区间查找值为val的元素,找到,则返回其迭代器,否则返回最后一个元素后的迭代器位置。search(begin1,end1,begin2,end2)search函数查找区间begin2到end2的值序列在区间begin1到end1的首次出现的位置,找到则返回其首次出现的迭代器位置,否则返回最后一个元素后的迭代器位置。【例12-13】非更易算法应用案例。Twelvth_13.cpp12.3.2更易型算法常用函数原型说明:(1)copy(begin,end,iteratorp);(2)transform(begin1,end1,begin2,operation)(3)merge(begin1,end1,begin2,end2,result,compare)(4)replace(begin,end,Tbefore,Tsub);(5)replace_if(begin,end,boolpred,Tsub);【例12-14】更易型算法应用举例。Twelvth_14.cppcopy(begin,end,iteratorp);copy完成将某容器begin到end区间的元素拷贝到另一个以p作为开始位置的容器中。其中第三次个参数也可以为back_inserter()、inserter(
,)或front_inserter()的函数。例如:copy(v.begin,v.end,back_inserter(v1));
该语句的作用是将v中元素插入到容器v1中,且每个元素每次都从v1的末尾插入。而front_inserter()则正好相反。inserter(v1,p)则指定插入到容器v1从p开始的某个位置。move函数则和copy函数用法类似,但区别是move的区间可以重叠transform(begin1,end1,begin2,operation)Transform函数将第一个以begin1开始到end1区间的元素执行operation操作后复制到以begin2开始的某区间中。merge(begin1,end1,begin2,end2,result,compare)
该函数将某容器从begin1到end1区间的元素和另一容器从begin2到end2区间的元素按照compare定义的规则合并到容器result中,前提要求容器1和容器2中的元素都必需有序。replace(begin,end,Tbefore,Tsub);该函数作用是将容器从begin到end区间的元素before用sub替换。replace_if(begin,end,boolpred,Tsub);该函数作用是将容器从begin到end区间的使得函数pred为真的元素用sub替换。12.3.3移除型算法提示:移除型算法只是从“逻辑上”移除元素,其手段是将不应移除的元素往前覆盖应被移除的元素,因此其并未改变操作区间内元素的个数,而是返回逻辑上新终点的位置。常用移除算法原型:iteratorremove_if(iteratorbegin,iteratorend,boolpredict)
iteratorremove_copy(iteratorbegin1,iteratorend1,iteratorbegin2,typeval);
iteratorunique(iteratorbegin,iteratorend);【例12-15】移除函数应用案例。Twelvth_15.cppremove_if:他将满足某一个规则的元素移除,移除后返回容器的新的最后一个元素位置。函数的一般形式为:iteratorremove_if(begin,end,predict);其中begin和end为执行移除操作的对应容器的开始和结束迭代器,第三参数predict为返回值为bool类型的函数。意思是将容器中使得predict为真的元素移除。remove_copy将某元素值从容器中移除,并将其余元素拷贝到另一个容器,返回最后一个被拷贝的元素在容器中的位置。iteratorremove_copy(begin1,end1,begin2,val);其中参数begin和end为执行移除操作的容器的开始和结束迭代器,begin2为拷贝容器的开始迭代器,val为要移除的元素。unique:将移除相邻的重复值,返回逻辑上未被删除的最后一个元素的下一个迭代器值。其函数原型为:
iteratorunique(begin,end);其中begi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年中国汽车水箱烘焊炉市场调查研究报告
- 2025年中国抽桶市场调查研究报告
- 支架术后定期复查与随访管理
- 特别护理记录单的国际化趋势
- 人工智能辅助护理技术
- 药物过敏的护理创新方法
- 卧床老人心理障碍护理与干预
- 给排水工程施工方案
- 护理专业能力评估中的跨专业合作
- 痔疮术后个人卫生护理技巧
- 人教部编版道德与法治八年级下册道德与法治期末测试检测试题(解析版)
- 2024年北京中考语文试题及答案
- 新青岛版-二年级下册数学-口算题
- 周志华-机器学习-Chap01绪论-课件
- X矿业企业120万t选矿厂投标文件技术标
- 汉语写作与百科知识样题
- 提高喷射混凝土施工一次验收合格率QC成果
- 美丽中国(支教项目)
- 题型01 长句表达题的规范答题(课件) 高考生物二轮复习 (新教材专用)
- GB/T 17467-2020高压/低压预装式变电站
- 新通用设备经济寿命参考年限表
评论
0/150
提交评论