容器
容器是容纳特定类型对象的集合,容器的类型分为顺序容器,容器适配器和关联容器,顺序容器将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素。
顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。标准库定义了三种顺序容器类型:vector,list和deque。他们得差别在于访问元素的方式,以及添加或删除元素相关操作的运行代价。
适配器是根据原始容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。顺序容器适配器包括stack,queue和priority_queue类型。
标准库还定义了几种关联容器,其元素按照key排序。
标准库为容器类型定义的操作强加了公共的接口。这些容器类型的差别在于他们提供哪些操作,但如果两个容器提供了相同的操作,则他们的接口(函数名和参数个数)相同。容器类型的操作集合层次如下
1.一些操作适用于所有容器类型;
2.一些操作只适用于顺序或关联容器类型的一个子集;
3.一些操作只适用于顺序或关联容器类型类型的一个子集;
顺序容器
顺序容器的初始化以及定义
使用顺序容器首先要包含头文件:
#include<vector> #include<list> #include<deque>
顺序容器的定义
vector<int> vec;//所有容器是模板 list<int> lis;//<>中提供容器中存放的元素的类型,可以是常用数据类型也可以是自己定义的类类型</span> deque<int> items;//容器类型都定义了默认构造函数用于创建指定类型的空容器对象,默认构造函数不带参数
顺序容器的初始化
vector<int> vec;//定义包含int型元素的容器 vector<int> vec1(10);//包含10个int型元素的容器 vector<int> vec2(10,1);//包含10个int型元素的容器每个被初始化为1,只适用于顺序容器 vector<int> vec3(vec2);//将vec2中的元素复制到vec3,只适用于顺序容器
不能直接将一种容器中的元素赋值给另一种容器,但是可以使用传递一对迭代器间接实现该功能
vector<string> svec; list<string> ilist(svec);//容器不同,不能复制 list<string>slist(svec.begin(),svec.end());//使用迭代器,不要求容器类型相同
注:除引用类型外,所有内置或复合类型(包括容器类型本身)都可以用做元素类型,IO库类型不能够作为容器类型;
当使用类类型作为元素类型,如果指定了容器的大小,则必须提供单个初始化式的构造函数。
vector< <vector<string> >lines;
顺序容器的操作
顺序容器的类型别名
begin和end成员
所有容器都提供begin和end操作符,用于返回迭代器,begin返回迭代器指向的第一个元素,end返回迭代器指向的容器末端的元素下一个,它指向一个不存在的元素,当容器为空,两个操作符返回的值相等。
容器中添加元素
容器支持以下操作添加新元素:
任何insert和push操作可能导致迭代器失效,当编写程序时,程序必须确保迭代器在每次插入操作后更新。要避存储end操作返回的迭代器。
关系操作符
所有容器都支持关系操作符来比较容器中的元素,比较时,容器类型,容器中元素的类型都必须相同。容器比较是基于容器内元素的比较,即其内部元素类型定义的比较操作。如果容器的元素类型不支持某种操作符,则该容器不能做比较运算。
容器大小操作
访问元素
删除元素
赋值和swap
使用赋值操作符时,赋值前两容器长度可以不相等,但赋值后两容器都具有右操作数的长度。
=和assign会使左操作数容器的所有迭代器失效,swap不会。
assign可以实现类型不同但相互兼容的元素的赋值。
swap实现交换两个容器内所有元素的功能,要交换的容器类型必须匹配,操作数必须是相同类型的容器,而且所存储的元素类型也必须相同。
capacity和reserve
由于vector元素以连续方式存放,当添加了新元素,但是容器中已经没有容纳新元素的空间,就回重新分配内存空间,将就空间的存储的元素复制进去,接着插入 新元素,最后撤销旧的存储空间。为了使vector实现快速内存分配,其实际分配的容量要比当前所需的空间多一些。
vector提供两个成员函数capacity和reserve来与容器的内存分配实现交互。
capacity操作获取在容器需要分配更多存储空间之前能够存储的元素总数,通常比size要大。
reserve操作告诉容器应该预留多少个元素的存储空间。
容器适配器
适配器是使一个事物的行为类似于另一个事物的行为的一种机制,适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。如:stack可使任何一种顺序容器以栈的方式实现。
使用适配器必须包含头文件
#include<stack> #include<queue>
容器适配器的通用操作和类型
适配器的初始化
所有适配器都有两个构造函数1.默认构造函数:常见空对象2.带一个容器参数的构造函数:将参数容器的副本作为基础值
deque<int>deq; stack<int>stk(deq);
覆盖基础容器类型
默认的stack和queue都是基于deque容器实现,而priority_queue则在vector容器上实现。
如果要覆盖其关联的容器类型,可通过将一个顺序容器指定为适配器的第二个类型实参:
stack< string,vector<string> >str_stk;
对于给定的适配器,关联的容器必须满足一定的约束条件
stack可以关联所有的顺序容器;
queue要求关联的容器支持push_front,因此只能建立在list和deque上;
priority_queue要求提供随机访问功能,因此只建立在vector和deque上;
栈适配器
栈的操作如下:
所有的容器适配器都依据其基础容器类型所支持的操作来定义自己的操作,比如,stack建立在deque容器上,因此采用deque提供的操作来实现栈功能。
队列和优先队列
priority_queue允许用户为队列中存储的元素设置优先级,这种队列不是直接将新元素放置在队列尾部,而是放在比它优先级低的元素前面。
迭代器和迭代器操作
迭代器是一种检查容器内部元素并且遍历元素的数据类型,标准库为每一种标准容器定义了一种迭代器类型,如vector迭代器:
vector<int>::iterator iter
所有迭代器都具有相同的接口,例如迭代器可使用解引用操作符(*操作符)来访问迭代器所指向的元素
*iter=0//将iter指向的值设为0.
下表迭代器为所有标准库容器类型所提供的运算
deque和vector还提供了额外的操作符
vector和deque这两种容器为其元素提供快速随机访问,而list只支持自增自减以及相等不等运算。
const_iterator
该类型只能用于读取容器内元素但不能改变其值。
各种容器的比较
vector:提供元素的随机访问,除容器尾部外,在容器任何其他位置上插入(或删除)操作都要求移动被插入(或删除)元素右边的所有元素。
list:表示不连续的内存区域,可高效的在任何位置插入和删除一个元素,但是不支持随机访问
deque:在deque队列的两端插入和删除元素非常快,同时deque具有以下性质:1.在容器中间插入或删除效率比较低;2.可高效地在其首部实现插入和删 除,就像在容器尾部 一样;3.支持对所有元素的随机访问;4.在容器首部或尾部插入元素不会使任何迭代器失效,而在首部或者尾部删除则会使指向被删除元素的迭代器时效,在任何其他位置的插入和删除操作将使指向该容器元素的所有迭代器都失效。
版权声明:本文为博主原创文章,未经博主允许不得转载。