收藏 分享(赏)

STL教材详解.ppt

上传人:fmgc7290 文档编号:8119622 上传时间:2019-06-09 格式:PPT 页数:33 大小:206KB
下载 相关 举报
STL教材详解.ppt_第1页
第1页 / 共33页
STL教材详解.ppt_第2页
第2页 / 共33页
STL教材详解.ppt_第3页
第3页 / 共33页
STL教材详解.ppt_第4页
第4页 / 共33页
STL教材详解.ppt_第5页
第5页 / 共33页
点击查看更多>>
资源描述

1、STL( Standard Template Library),STL (标准模板库): 是C+标准程序库的核心,是一个泛型程序库,提供了一系列软件方案,利用先进,高效的算法来管理数据。从程序员角度看,STL是由一些可适应不同需求的群集类别和一些能够在这些数据群集上运作的算法构成。STL内部的所有组件都由template构成,所以其元素可以是任意型别。 STL组件:最关键的是容器,算法,迭代器 STL的基本观念就是将数据和操作分离。数据由容器类别加以管理,操作则由可定制的算法定义之。迭代器在两者之间充当粘合剂,使任何算法都可以和任何容器交互运作。 STL将数据和算法分开对待,而不是合并考虑。从

2、某种意义上说,STL的概念和面向对象程序设计(OOP)的最初思想是矛盾的。但是,这么做有很重要的原因:你可以将各种容器与各种算法结合起来,在很小的框架内拥有非常大的弹性。STL的一个根本特性是,所有组件都可以针对任意型别运作。 STL还提供了更泛型化的组件,通过特定的配接器和仿函数,你可以补充,约束或定制算法,以满足特别需求。,容器(Containers),容器:用来管理某类对象的集合。容纳特定数据类型对象的集合,STL容器是将最常用的一些数据结构实现出来.包含了许多数据结构,如:vector,queue,statck,string也可以看作是一个容器. 分类:容器用来管理一组元素,为了适应不

3、同需要,STL根据数据在容器中排列的特性,容器可分为序列式容器和关联式容器两种. 序列式容器:可序群集,其中每个元素都有固定位置取决于插入时机和地点,与元素的值没有关系,如果你以追加方式对一个群集置入n个元素,它们的排列次序将和置入次序一致。如vector,deque,list 关联式容器:已序群集,元素位置取决于特定的排序准则,和插入顺序无关。如果你将n个元素置入这样的群集中,它们的位置取决于元素值,和插入次序无关。STL提供了4个这样的容器:set,map,。multiset,multimap。关联式容器也可被视为特殊的序列式容器,因为已序群集正是根据某个排序准则排列而成。,算法(Algo

4、rithms),算法:用来处理群集内的元素。它们可以出于不同的目的而搜寻,排序,修改,使用那些元素。是一种应用在容器上以各种方法处理其内存的行为或功能,如sort(排序),copy(拷贝),算法由模板函数体现,这些函数不是容器类的成员函数,是独立的函数,它们可以用于STL容器,也可以用于普通的C+数组等. 头文件:#include在STL的泛型算法中有4类基本的算法: 1)变序型队列算法: 可以改变容器内的数据; 2)非变序型队列算法:处理容器内的数据而不改变他们; 3)排序值算法:包涵对容器中的值进行排序和合并的算法,还有二叉搜 索算法 , 4)通用数值算法:此种算法不多,涉及到专业领域中有

5、用的算术操作,独立包涵于头文件中,在此不多做解释,STL的算法并不只是针对STL容器,对一般容器也是适用的。 变序型队列算法 #include #include #include /下面用到了输出迭代器ostream_iterator using namespace std; int main(void) int arr6=1,12,3,2,1215,90;int arr17;int arr26=2,5,6,9,0,-56;copy(arr,(arr+6),arr1);/将数组aar复制到arr1cout(cout, “ “);/复制到输出迭代器swap_ranges(arr,arr+6,ar

6、r2);/交换arr和arr2序列cout(cout, “ “);cout(cout, “ “);return 0; ,非变序型队列算法 #include #include #include using namespace std; int main(void)int a10=12,31,5,2,23,121,0,89,34,66;vector v1(a,a+10);vector:iterator result1,result2;/result1和result2是随机访问迭代器result1=find(v1.begin(),v1.end(),2);/在v1中找到2,result1指向v1中的2

7、 result2=find(v1.begin(),v1.end(),8);/在v1中没有找到8,result2指向的是v1.end() cout v2(a+2,a+8);vector v3(b,b+4);result1=search(v1.begin(),v1.end(),v2.begin(),v2.end();cout v4(b,b+9); int i=count(v4.begin(),v4.end(),5);int j=count(v4.begin(),v4.end(),2);cout“there are “i“ members in v4 equel to 5“endl;cout“the

8、re are “j“ members in v4 equel to 2“endl; /计算v4中有多少个成员等于 5,2return 0; ,排序值算法#include #include using namespace std; int main(void) int a10=12,0,5,3,6,8,9,34,32,18;int b5=5,3,6,8,9;int d15;sort(a,a+10);for(int i=0;i10;i+)cout“ “ai;sort(b,b+5); / 3 5 6 8 8if(includes(a,a+10,b,b+5) /一个数组是否包含另外一个数组cout“n

9、“sorted b members are included in a.“endl;elsecout“sorted a dosnt contain sorted b!“;merge(a,a+10,b,b+5,d); /合并for(int j=0;j15;j+) cout“ “ dj; return 0; ,迭代器,迭代器:用来在一个对象群集的元素上进行遍历动作。这个对象群集或许是个容器,或许是容器的一部分。迭代器的主要好处是,为所有容器提供了一组很小的公共接口,利用这个接口,某项操作就可以行进至群集内的下一个元素。每一种容器都提供了自己的迭代器,而这些迭代器了解该种容器的内部结构,所以能够知道

10、如何正确行进。迭代器的接口和一般指针差不多。 可将其看作是一个指向容器中元素的普通指针,用迭代器来访问容器中的元素,是它将算法和容器连接在一起,每个容器都有自己的迭代器,只有容器自己才知道如何访问自己的元素.,容器类别的共通操作函数,ContType c 产生一个空容器 ContType c1(c2) 产生一个同型容器 ContType c3(beg,end) 用beg,end区间值 给容器赋初值 C.ContType() 析构,释放内存 C.size() 返回容器中的元素数量 C.empty() 判断容器是否为空 C.max_size() 返回元素的最大可能数量,c1 = c2 判断是否c1

11、等于c2 c1 != c2 判断是否c1不等于c2 c1 c2 判断是否c1大于c2 c1=c2 判断是否c1大于等于c2 c1 = c2 将c2的所有元素赋值给c1 c1.swap(c2) 交换c1和c2的数据 swap(c1,c2) 同上,是全局函数 c.clear() 移除所有元素,使容器为空,c.erase(beg,end)移除beg,end区间内所有元素,某些容器会 返回未被移除的第一个接续元素 c.insert(pos,elem)将elem的一份副本安插于pos处,返回值和pos的意义并不相同 c.begin()返回一个迭代器,指向第一元素 c.end()返回一个迭代器,指向最后元

12、素下一个位置 c.rbegin() 返回一个逆向迭代器,指向逆向遍历时第一元素 c.rend()返回一个逆向迭代器,指向逆向遍历时最后元素的 下 一位置 c.get_allocator()返回容器的内存模型,vector,Vector:将其元素置于一个动态数组中加以管理。是一种动态数组,是基本数组的类模板,可用于代替C中的数组,能够存放各种类型的对象,能够增加和压缩数据。它支持随机存取,也就是说你可以利用索引值直接存取任何一个元素。在array尾部附加元素或移动元素非常快速,但是在array中部或头部安插元素就比较费时,因为,为了保持原本的相对次序,插入点之后的所有元素都必须依次移动。 Vec

13、tor头文件:#include,vecotr,Vector是一个类,有自己的构造函数,在vector类中定义了4种构造函数,分别如下操作: Vectora; Vectorb(5,0); Vectorc(b); Vectord(m,m+5); 具体例子如下所示,Vector中大小和容量的问题 Size()告诉你容器中有多少个元素,没有告诉你容器为它所能容纳的元素分配了多少内存 Capacity()容器在它已经分配的内存中可以容纳多少元素,是总共可以容纳的元素. Resize(n)强制把容器改为容纳n个元素 Reserve(n)强制容器把它的容量改为至少n,提供的n不小于当前大小,使用此函数不改变

14、容器中对象的个数. 有了这个大小和容量的函数,可以让我们知道什么时候往容器插入元素将引起容器执行重新分配空间,而且可以知道什么时候插入会使指向容器的迭代器指针引用失效. If(s.size() s.capacity() s.push_back(5);此句插入不会使指向这个容器的迭代器指针失效,vector的函数,Vector还有以下函数: capacity():返回重新分配空间前所能容纳的元素最大数量 reserve():如果容量不足,扩大之 c.assign(n,elem):复制n个elem,赋值给c c.assign(beg,end):将区间beg,end内的元素赋值给c c.at(ind

15、ex):返回索引为index的元素,如果越界,则抛出异常 cindex:返回索引为index的元素,不检查错误 c.front():返回第一个元素,不检查第一个元素是否存在 c.back():返回最后一个元素,不检查最后一个元素是否存在 c.insert(pos,elem):在pos位置上插入一个elem,并返回新元素位置 c.insert(pos,n,elem):在pos位置插入n个elem,无返回值 c.insert(pos,beg,end):在pos位置插入区间beg,end内的所有元素副本,无返回子 c.push_back(elen):在尾部添加一个elem c.pop_back():

16、移除最后一个元素(但不回传) c.erase(beg,end):移除beg,end区间内的所有元素,返回下一个元素的位置 c.resize(num):将元素数量改为num(如果size变大,多出来的新元素都需以默认构造函数构造) c.resize(num,elem):将元素数量改为num(如果size变大,多出来的新元素都是elem的副本),Vector中访问元素的问题,访问vector中的元素,可以像访问数组元素一样使用下标形式,即(an),也可以用vector中提供的函数at,即(a.at(n)),但是一般情况下建议使用at,因为at会进行边界检查,如果访问超过了vector的范围,则会抛

17、出异常,但是用数组下标的形式不会出现这种检查。只是结果会出现意想不到的值。 例如:#include #include using namespace std; void main() int a = 1,2,3,4,5;int n = sizeof(a)/sizeof(int);vectorb(a,a+n);coutanendl; /不会报错,结果意想不到coutb.at(n)endl; /会出现异常 ,vector插入元素操作 #include #include using namespace std; int main(int argc, char* argv) vector v;v.pu

18、sh_back(6);v.push_back(7);v.push_back(8);v.push_back(10);v.insert(v.begin()+3,9);/10前插入v.insert(v.begin(),5);/首位插入v.insert(v.end(),11);/最后插入vector:iterator i,iend;int j;for( i=v.begin(),j=0; i != v.end(); i+,j+)cout “V“ j “ *i endl;return 0; ,vector元素删除 #include #include using namespace std; void ma

19、in(int argc, char* argv) vector v;v.push_back(6);v.push_back(7);v.push_back(8);v.push_back(10);v.insert(v.begin()+3,9);/10前插入v.insert(v.begin(),5);/首位插入v.insert(v.end(),11);/最后插入v.erase( v.begin() );/删除第一个 vector:iterator i;int j;for( i=v.begin(),j=0; i != v.end(); i+,j+)cout “V“ j “ vjendl;v.erase(

20、v.begin(),v.begin()+2);/删除前2个for( i=v.begin(),j=0; i != v.end(); i+,j+)cout “V“ j “ vjendl;v.clear();/删除全部元素 ,deque,Deque:双端队列,它是一个动态数组,它支持随机读取,可以向两端发展,因此不论在尾部或者头部插入元素都非常快,但是在中间部分插入元素则比较费时,此时必须移动其他元素。与vector不同的是,deque支持从头部插入元素。提供了成员函数push_front() 头文件:#include 例题:,deque,#include #include #include usi

21、ng namespace std; void main() deque a;int i = 0;for(;i:iterator iter; /迭代器操作for(iter = a.begin();iter != a.end();iter+)cout*iter“ “;coutendl;sort(a.begin(),a.end(); /用sort函数进行排序,默认方式是从小到大cout“排序后的结果“endl;for(iter = a.begin();iter != a.end();iter+)cout*iter“ “;coutendl; ,void main() /创建dequedeque d1;

22、 /创建一个没有任何元素的deque对象deque d2(10);/创建一个具有10个元素的deque对象,每个元素值为默认deque d3(10, 5.5); /伊妹一个具有10个元素的deque对象,每个元素的初始值为5.5deque d4(d3); /通过拷贝一个deque对象的元素值, 创建一个新的deque对象deque d5(10,6);/初始化赋值:同vector一样,使用尾部插入函数push_back()for (int i = 1; i 6 ; i+)d1.push_back(i*10);/遍历元素: 1-下标方式 2-迭代器方式 反向遍历(略)cout“printDeque

23、(d1) : “endl;printDeque(d1);/元素插入:尾部插入用push_back(),头部插入用push_front(),其它位置插入用insert(,cout“d1.erase(d1.begin(), d1.begin() + 2) = “endl;d1.erase(d1.begin(), d1.begin() + 2);printDeque(d1);cout“d1.clear() :“endl;d1.clear();printDeque(d1);/其它常用cout“其它常用用法: “endl;int flag = 0;while(flag 2)if (0 = flag )

24、for (int i = 1; i 6 ; i+) /恢复d1.push_back(i*10);else d1.clear();cout“after d1.clear() , d1.front(), d1.back() is abnormal! other info.:“endl;cout“d1.empty() = “d1.empty()endl;cout“d1.size() = “d1.size()endl;cout“d1.max_size() = “hexd1.max_size()endl;if ( !d1.empty() ) cout“d1.front() = “d1.front()en

25、dl;cout“d1.back() = “d1.back()endl; flag+; /交换cout“d1.swap(d5)= “endl;d1.swap(d5);cout“d1 = “;printDeque(d1);/printDeque(d) ,void printDeque(deque d) /使用下标/for (unsigned int i = 0; i :iterator iter = d.begin();/for (;iter != d.end(); iter +)/ cout:iterator *pIter = new deque:iterator;if ( NULL = pIt

26、er ) return ;for (*pIter = d.begin(); *pIter != d.end(); (*pIter)+) cout“d“*pIter - d.begin() “=“*pIter“, “;if (NULL != pIter) delete pIter;pIter = NULL;coutendl; ,list,List:由双向链表实作而成。故list内的每个元素都以一部分内存指示其前趋元素和后继元素。List不提供随机存取,只能顺序访问,如果要访问表中某项需要从表头或表尾开始循环,而且没有下标运算符。 List优点:在任何位置上执行插入或者删除动作都非常快速,因为只需

27、要改变链接就可以。这样在list中间位置移动元素比在vector和deque快很多。 头文件:#include,List小结: 1.不能随机读取 2.插入删除速度快 3.插入删除不会造成指向它的各个元素的指针,引用和迭代器失效 4.不提供访问和at()访问方法 5.不提供容量,重新分配操作 6.它本身提供了一些特殊成员函数来完成移动操作,比通用算法的函数性能好,用STL通用算法for_each来处理list中元素 #include #include #include #include using namespace std; PrintIt (string ,vector,list,queue

28、比较,Vecotr和数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此能支持随机读取,但由于它的内存空间是连续的,在中间插入和删除元素会造成内存的拷贝,而且,当该数组后的内存空间不够时,需要重新申请一块足够大的内存并进行内存的拷贝,这样就影响了它的效率. List就是数据结构中的双向链表,它的内存空间是不连续的,通过指针来进行数据的访问,随机读取不方便,没有提供操作符,但是它支持任意地方的插入和删除. Queue,它支持,可以随机读取,和vector差不多,也支持在两端操作,此操作与list效率也差不多.由此得出结论:如果需要随机读取数据,而且两端可操作,则应该使用deque如果需要高

29、效的随机读取,而不在乎插入和删除的效率,用vector如果需要大量的插入和删除,不关心随机读取,使用list,map,map:一对一的数据映射,如果某个事物满足一对一的数据映射关系,就可以用map来表示.与数据库表的具有键值的记录非常相似,由一个键值和其他若干数据组成,键值和映射数据之间,可建立一个数学上的映射关系。插入的元素键值不允许重复,所使用的节点元素的比较函数,只对元素的键值进行比较,元素的各项数据可通过键值检索出来。,#include #include using namespace std; void main() map m;m“apple“ = 8.6f;m“orangle“

30、= 3.2f;m“banana“ = 2.8f;m“pear“ = 3.8f;m“lichee“ = 7.6f;m“barry“ = 8.2f;cout “苹果“ m“apple“ “元/斤n“; ,函数作为算法的参数,一些算法可以接受用户定义的辅助性函数,由此提高其灵活性和能力,这些函数将在算法内部被调用。 例如: #include #include #include using namespace std; void print(int num) cout vct;int i = 1;for(;i=9;i+)vct.push_back(i);for_each(vct.begin(),vct

31、.end(),print);coutendl; ,函数对象(仿函数),传递给算法的“函数型参数”,并不一定得是函数,可以是行为类似函数的对象,这种对象称为仿函数,当一般函数使不上劲时,你可以使用仿函数,STL大量运用仿函数,也提供了一些很有用的仿函数。 什么是仿函数?仿函数是泛型编程强大威力和纯粹抽象概念的又一个例证。任何东西,只要其行为像函数(指可以“使用小括号传递参数,藉以调用某个东西”),它就是一个函数。如果你定义了一个对象,行为像函数,它就可以被当做函数来用。 将函数封装在一个对象中,使得它可以作为参数传递给合适的STL算法,从而使得算法的功能得以扩展,可以把它当作函数来使用,其实就是

32、在类里面定义重载()运算符,让一个类能象一个函数一样使用.,例如:#include #include #include using namespace std; struct Print void operator()(int num)constcout vct;int i = 1;for(;i=9;i+)vct.push_back(i);for_each(vct.begin(),vct.end(),Print();coutendl; 代码详解:Print类表明,可以用它的对象调用operator(),并传一个int参数,for_each(vct.begin(),vct.end(),Print

33、(); 此语句中Print(),产生出一个类Print的临时对象,当做for_each()的参数。此算法大致如下所示: namespace std templateOperation for_each(Iterator act,Iterator end,Operation op)while(act != end)op(*act);+act;return op; ; for_each()使用临时对象op(一个仿函数)针对每个元素调用op(*act),如果第三个参数是一个一般函数,就以*act为参数调用。如果第三个参数是个仿函数,则以*act为参数,调用仿函数op的operator()。,仿函数比起一般函数有下列优点 1.仿函数是智能型函数。仿函数可拥有成员函数和成员变量,这意味着仿函数拥有状态。事实上,在同一时间里,由某个仿函数所代表的单一函数,可能有不同的状态,这在一般函数中式不可能。而且,可以在执行期初始化它们。 2.每个仿函数都有自己的型别。 3.仿函数通常比一般函数速度快,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报