c++顺序容器
- 定义和初始化
#include<vector>
#include<list>
#inlcude<deque>
初始化:
C<T> c; 空容器,如vector<int> ivec; C c(c2); 创建容器c2的副本c C c(b,e); 由迭代器b,e标识的范围内的元素的副本,如list<int> ilist(ivec.begin(),ivec.end()); C c(n,t); 用n个值为t 的元素创建容器c C c(n); 创建有n个值初始化元元素的容器
string strings[]={"abc","def",ghi"};
deque<string> sdeq(strings,strings+sizeof(strings)/sizeof(string));
容器元素类型必须满足以下两个条件:
元素类型必须支持赋值运算;
元素类型的对象必须可以复制;
除了引用类型外,所有的内置类型或复合类型都可以用做元素类型。(引用不支持一般意义上的赋值运算),另外,IO类型不支持复制或赋值,故不能创建存放IO类型对象的容器。
容器存放的是复本,对于由其它容器或对象初始化的容器来说,更改其值不会影响被复制的原值。
容器的容器:
vector<vector<string> > lines;
>>中间要使用空格:
vector<vector<string>> lines;//error - 迭代器
迭代器为所有标准库容器类型所提供的运算:
*iter iter->item ++iter iter1==iter2 iter1!=iter2
vector和deque容器的迭代器提供的额外运算:(迭代器算术运算)
iter + n
iter - n
iter1+=iter2
>,>=,<,<=
上述只用于vector和deque容器,因为只有这两种容器为其元素提供快速,随机的访问。 - 容器操作
容器定义的类型别名:
size_type UL,最大可能长度,作为索引的类型 iterator 此容器类型的迭代器类型 const_iterator 只读迭代器 reverse_iterator 按逆序寻址元素的迭代器 const_reverse_iterator 只读逆序迭代器 difference_type 足够存储两个迭代器差值的有符号整型,可负 value_type 元素类型 reference 元素左值类型,是value_type&的同义词 const_reference 元素常量左值类型,等效于const value_type&
关系操作符:
所有容器都支持关系操作符来实现来个容器的比较。比较的容器必须要有相同的容器类型,且元素类型也要相同。容器的比较是基于容器内元素的比较,故元素应要支持关系操作。
容器大小操作:
c.size()//当前大小
c.max_size()//可容纳最大数
c.empty()
c.resize(n)//调整大小为n,若n>c.size(),添加值采用初始化方法,否则删除多余值
c.resize(n,t)//调整大小为n,若n>c.size(),添加值为t,否则删除多余值
元素访问:
如果容器非空,则front和back成员将返回容器内第一个或最后一个元素引用:
if(!ilist.empty())
{
list<int>::reference val=*ilist.begin();//引用
list<int>::reference val2=ilist.front();//和val相同
list<int>::reference last=*--ilist.end();
list<int>::reference last2=ilist.back();
}
汇总:
c.back()
c.front()
c[n] //only vector and deque suported ,no list
c.at(n) //only vector and deque suported ,no list
删除元素:
c.erase(p) 删除迭代器指向的元素,返回指向删除元素的下个元素的迭代器,若p为c.end()则函数未定义 c.erase(b,e) 删除迭代器b和e范围内的元素,返回指向删除元素段的下个元素的迭代器,若e为c.end(),则返回c.end() c.clear() 删除c中所有元素,返回void c.pop_back() 删除最后一个元素,返回void,若c为空,则函数未定义 c.pop_front() 删除第一个元素,返回void,若c为空,则函数未定义,只适用于list或deque
string searchValue("Quasimodo");
list<string>::iterator iter=find(slist.begin(),slist.end(),searchValue);
if(iter!=slist.end())
slist.erase(iter);
赋值与swap
c1=c2 删除c1中所有内容,将c2的元素复制给c1。c1和c2的类型必须相同 c1.swap(c2) 交换内容:类型要相同。执行速度通常比将c2的元素复制到c1的操作快 c.assign(b,e) 重设c的元素:将迭代器b和e标记的范围内的元素复制到c中。b和e不能指向c中的元素 c.assign(n,t) 将c重设为存储n个值为t 的元素
当在不同或相同的容器中,元素类型不相同但是相互兼容,则其不能用=进行赋值,要用assign赋值。
swap:容器类型相同,元素类型相同。
c1.swap(c2);
swap操作没有移动元素,因此迭代器没有失效。比如在交换前,一个迭代器指向c1[2],实现交换后,该迭代器指向c2[2],指向的仍是同一个对象。
- 容器自增长
为了使vector容器实现快速的内存分配,vector容器预留了额外的存储区用于存放新加的元素。
由于vector是在内存中连续存放的,vector容器处理内存分配的细节是其实现的一部分,该部分是由vector的接口去持的。vector类提供了两个成员函数:capacity和reserve,使程序员可与vector容内存分配的实现部分的交互工作。capacity操作获取在容器需要分配更多的存储空间之前能够存储的元素总数,而reserve操作告诉vector容器应该预留多少个元素的存储空间。
size是指容器当前拥有的元数总数,而capacity是指容器在必须分配新的存储空间之前可以存储的元素总数。
vector<int> ivec;
cout<<"ivec:size: "<<ivec.size()<<endl; //0
cout<<"ivec:capacity:"<<ivec.capacity()<<endl; //0
//加入24个元素后
size:24
capacity:32
ivec.reserve(64);
size:24
capacity:64
//再加入24个元素后
size:48
capacity:64 //使用了预留的容量,不分配空间
//再加入24个元素
size:7
capacity:128//重新分配存储空间,以加倍当前容量的分配策略分配(依编译器变化) - 容器选择
Vector Deque List 随机访问 快速 快速 不支持 insert/erase 效率低 效率最低 快速 push_front() 不支持 快速 快速 push_back() 快速 快速 快速 pop_front() 不支持 快速 快速 pop_back() 快速 快速 快速
list不支持随机元素访问:
ilist.at(0);//error
ilist[0];//error
vector不支持push_front(val)和pop_front()操作。
选择容器的提示:
A.如果程序要求随机访问元素,则应使用vector或deque容器。
B.如果程序必须要在中间位置插入或删除元素则应采用list容器。
C.如果不需要在中间插入或删除元素,而是在首或尾部插入或删除元素,则应采用deque容器。
D.如果只需在读取输入时在容器的中间位置插入元素,然后需要随机访问元素,则可考虑在输入时将元素读入到一个list容器中,接着对此容器重新排序,使其适合顺序访问,然后将排序后的list容器复制到vector中。
E.如果程序既需要随机访问又必须在容器的中间位置插入或删除元素,此时选择何种容器取决于下面两种操作的代价:随机访问list的代价,在vector或deque容器中插入/删除元素时复制元素的代价。 - string和容器
string类型支持大多数顺序操作,在某些方面可将string类型视为字符容器。与vector容器不同的是,它不支持以栈方式操纵容器:在string类型中不能使用front,back和pop_back操作。
string 不支持的容器操作:
C<T> c(n) 初始化
push_front(e)
back,front
pop_back() pop_front()
关于string的具体介绍请参阅:《关于C++标准库中的 string》一文 - 容器适配器
除了顺序容器,标准库还提供了三种顺序容器适配器:queue,priority_queue和stack。
适配器支持的通用操作有:
size_type,value_type, container_type, A a; A a(c); 关系运算符
#include<stack>
#include<queue>
初始化:
两种方式:默认构造函数,空对象;带一个容器参数的构造函数将参数容器的副本作为其基础值。
例:假如deq是deque<int>类型的容器,则可用deq初始化一个新stack: stack<int> stk(deq);
覆盖基础容器类型:
默认的stack和queue都基于deque容器上实现,而priority_queue则在vector容器上实现。在创建适配器时,通过将一个顺序容器指定为适配器的第二个类型参数,可覆盖其关联的基础容器类型:
stack< string, vector<string> > str_stk; //implemented on top of vector
stack<string, vector<string> > str_stk(svec);//holds a copy of svec
stack 适配器要要所关联的容器可以是任意一种顺序容器,故可建立在vector,list或deuqe上。
queue适配器要求其关联的基础容器必须提供push_front运算,故只能建立在list容器上,不能建立在vector上。
priority_queue适配器要求提供随机访问的功能, 故可建立在vector或deque容器上,不能建立在list容器上。
栈适配器:
s.empty(),s.size(),s.pop(),s.top() ,s.push(item)
队列:FIFO queue
q.empty(),q.size(),q.pop(),q.front(),q.back(),q.push(item)