文章目录
顺序容器的类型
- vector(支持快速随机访问,除了容器尾部外,其余任何位置上的插入货删除操作都要求移动被插入或删除元素右边所有的元素,通常情况下是最佳容器)
- list(支持快速插入/删除,链表结构,访问某个元素要求遍历所涉及的其他元素)
- deque(支持快速随机访问,双端队列,在双端插入和删除元素都非常快,在容器中间插入或删除付出的代价将更高)
写代码时使用迭代器而不是下标,并且避免随机访问元素,这样在必要时可以将vector容器修改为list容器。
顺序容器适配器
- stack(基于deque容器实现,stack适配器所关联的基础容器可以是任意一种顺序容器类型,因此stack可以建立在vector、list和deque容器之上)
栈提供的操作:s.empty()/s.size()/s.pop()/s.top()/s.push(item)
- queue(基于deque容器实现,要求其关联的基础容器必须提供push_front运算,因此只能建立在list容器上,又称为FIFO queue)
- priority_quene(基于vector容器实现,要求提供随机访问功能,因此可以建立在vector和deque容器上,插入元素时不是在队尾位置而是放在比它优先级低的元素前面)
队列和优先级队列支持的操作:
q.empty()/q.size()/q.pop()/p.push(item)
q.back()//只适用于队列,返回队尾的值
q.top()//只适用于优先级队列,放回具有最高优先级的元素值。
1 顺序容器的定义
1.1容器元素的初始化
1.将一个容器初始化为另一个容器的副本
2.初始化为一段元素的副本(迭代器)
3.分配和初始化指定数目的元素
1.2容器内元素的类型约束
- 支持复制和赋值功能是容器元素类型的最低要求
- 容器的容器:
vector< vector<int> > lines;//注意必须加空格> >
2 迭代器
- ==和!=这两种关系运算符适用于所有容器
- {>,>=<.<=}关系操作符只适用于vector和deque容器,这是因为只有这两种容器为其元素提供快速、随机的访问。
- 迭代器范围[first,last),称为左闭合区间,不包括last,其指向最后一个元素的下一个位置
- 迭代器处理一段元素
while(first!=last) ++first;
- 注意使迭代器失效的容器操作:比如erase函数提供了删除容器元素的功能,任何指向已删除元素的迭代器具有无效值。
3 顺序容器的操作
1.在容器中添加元素
2.在容器中删除元素
3.设置容器大小
4.(如果有的话)获取容器内的第一个和最后一个元素
3.1 容器定义的类型别名
- size_type
- iterator
- const_iterator
- reverse_iterator
- const_reverse_iterator
- difference_type
- value_type
- reference
- const_reference
3.2 begin和end成员
- c.begin() //返回的是迭代器,需要解引用
- c.end()
- c.rbegin() //逆序
- c.rend()
3.3 在顺序容器中添加元素
所有的顺序容器都支持push_back()操作,提供在尾部插入一个元素的功能。
- c.push_back(t)
- c.push_front(t) (只支持list和deque容器类型)
- c,insert(p,t) //p前面插入值为t的元素,和push_front一样
- c.insert(p,n,t) //p前面插入n个值为t的元素
- c.insert(p,b,e) //p前面插入迭代器b和e标记的范围内元素
任何insert和push操作都可能使迭代器失效
不要存储end操作返回的迭代器,添加或删除deque或vector容器内的元素会导致存储的迭代器失效。
3.4 关系操作符
所有的容器类型都支持用关系操作符来实现两个容器的比较。比较的容器必须具有相同的容器类型。
3.5 容器大小的操作
- c.size() // 返回元素个数,返回类型为c::size_type
- c.max_size()
- c.empty()
- c.resize(n)//调整容器c的大小,使其能容纳n个元素
- c.resize(n,t)//同上,新添加的元素都为t
//如果resize操作压缩了容器,则指向已删除元素的迭代器失效
3.6 访问元素
- c.back() //返回容器c的最后一个元素的引用
- c.front()
- c[n] //返回下标为n的元素的引用,只适用于vector和deque
- c.at(n) //同上
if(!ilist.empty())//必须先判断是否存在
{
list<int>::reference val = *ilist.begin();
list<int>::reference val2 = ilist.front();
list<int>::reference last = *--ilist.end();
list<int>::reference last2 = ilist.back();
}
//使用下标运算符
vector<string> svec; //empty vector
cout << svec[0]; //runtime error
cout << svec.at(0); //throws out_of_range exception
3,7 删除元素
- c.erase( p) //删除迭代器p所指向的元素,返回一个迭代器,指向被删除元素后面的元素
- c.erase(b,e) //删除迭代器b和e所标记的范围内的所有的元素
- c.clear() //删除容器c内的所有元素,返回void
等同于c.erase(c.begin(),c.end()) - c.pop_back() //删除容器c的最后一个元素,返回void
- c.pop_front() //删除容器c的第一个元素,放回void。只适用于list和deque
//删除一个元素
//寻找一个指定元素的方法:find
#include<algorithm>
string searchValue(“Quasimodo”);
list<string>::iterator iter =
find(slist.begin(),slist.end(),seatchValue);
if(iter!=slist.end())
slist.erase(iter)
指向被删除元素的迭代器失效
3.8 赋值与swap
赋值操作符首先删除其左操作数容器中的所有元素,然后将右操作数容器的所有元素插入到左边容器中。
c1 = c2;
等同于
c1.erase(c1.begin(),c1.end());
c1.insert(c1.begin(),c2.begin(),c2.end());
等同于
c1.assign(c2.begin(),c2.end())
注:如果在不同类型的容器中,元素类型不相同但是相互兼容,则其赋值操作必须使用assign函数。可通过assign操作实现将vector容器中一段char *类型的元素赋给string类型的list容器。
- c1 = c2
- c1.swap(c2) //交换内容,执行速度比复制快,迭代器不会失效
- c.assign(b,e) //迭代器b和e标记的范围内所有元素复制到c中。b和e必须不是指向c中元素的迭代器
- c.assign(n,t) //将容器c重新设置为存储n个值为t的元素
4 vector容器的自增长
已知元素是连续存储的,当我们在容器内添加一个元素时:
1.重新分配空间(存放原来元素+新元素)
2.存放在旧存储空间的元素被复制到新存储空间
3.插入新元素
4.撤销旧的空间
为了使vector容器实现快速的内存分配,其实际分配的容量要比当前所需的空间多一些。
4.1 capacity 和 reserve成员
- capacity指容器在必须分配新存储空间之前可以存储的元素总数。size指容器当前拥有的元素个数。
- reserve告诉vector容器应该预留多少个元素的存储空间。
每当vector容器不得不分配新的存储空间时,以加倍当前容量的分配策略实现重新分配。