第九章:顺序容器
1、 顺序容器的元素按其位置存储和访问,其元素的排列元素的值无关,而是按其加入的顺序存储。 关联容器。其元素按键(key)来排序。
2、 标准库定义了三种顺序容器: vector/list /dequeue。 标准库还提供了三种容器适配器: 根据原始的容器类型所提供的操作,通过定义新的操作接口,来适应基础的容器类型。顺序容器:
vector:支持快速随机访问
List :支持快速插入和删除
Deque:双端对列顺序容器适配器:
stack:后进先出(LIFO)栈
Queue:先进先出(FIFO)队列
Priority_queue:优先级管理队列
3、 容器(包括关联容器)元素类型的约束: 必须支持赋值操作; 元素类型的对象必须可以复制。 关联容器的建还需要其他要求。
4、 由于引用不支持赋值操作,因此不可作为容器元素,同理IO库类型不支持赋值或复制因此不可作为容器元素。 容器本身满足上述要求,因此容器的元素可以使容器:vector<vector<string> > vec_str;//注意后面两个尖括号之间需要有空格。
5、 注意:vector 、deque:迭代器支持额外的运算:iter+n /iter-n/ iter1-iter2 />= /<= />等。一般其他迭代器只支持 自增 自减 相等== 或不等!=等运算符。 之所以vector和deque支持子迭代器加减n的操作,这正是基于他们所提供的快速随机访问特性。
6、 迭代器范围: 左开右闭。 如果beg等于end则说明迭代范围为空。
7、 必须 注意迭代器失效问题:添加元素可能会使得某些或者全部迭代器失效(insert push等),相当于垂悬指针。删除操作,会使得vector在删除点后面的所有迭代器失效;deque则会所有迭代器失效。
8、 注意:容器元素都是副本: 放入容器中的元素都是其原始值得副本。
9、 .insert(p_iter,val)插入操作将元素插入到指定位置(迭代器)的前面,并返回新插入元素的位置迭代器。如:vec.insert(vec.begin(), val);将val插入到容器的头部,并返回新元素(即头部的)迭代器begin(). 而删除erease是删除指定位置后面的元素,返回指向被删元素后面元素的迭代器。
10、注意:数组指针本身就是迭代器,因此在表示用一对迭代器表示范围时,可传入一对指针实参。
11、容器的关系操作符: 所有的容器都支持用关系操作符来实现两个容器的比较,比较的容器必须具有相同的类型,并其元素类型也要相同。 容器的比较是通过比较其元素来实现的。 比较类似于string的比较。如vector<int> vec1,vec2;的比较,通过从头到尾来一次比较两个容器中对应位置的元素的大小来决定容器的大小,具体策略按字符串的比较来处理。
12、访问顺序容器内的元素:back()/front()返回最后一个或第一个元素的的引用。 C[n]/c.at(n)返回下标位置为n的元素的引用,只适用于vector和deque。
13、容器赋值: c1=c2;//用容器2中的所有元素替代容器1中的所有元素。(这使得容器1的长度变为与容器2的长度相等。):过程:先删除c1中的所有元素,再将c2的容器复制到c1. 而交换函数swap则不用先删除,而是直接交换元素,效率高,且由于没有删除插入元素,因此原来的迭代器不会失效。如:vec1.swap(vec2);将2中的所有元素与1中的所有元素交换,要求容器和其中的元素类型一样。 交换前后同一迭代器指向同一元素,只是该元素在交换后到了另外一个容器中,因此该迭代器指向了另外的一个容器中的该元素。
14、Vector:只有到必要时才分配新的空间。 Size现有元素、capacity总容、reserver要求预留多大的空间。 在新加元素时,只有当capacity用完时才新分配空间。空间增长策略根据具体的实现决定,如增倍,或者增加0.5倍。
15、 Deque容器同时提供了lsit和vector的性质|:
(1)、与vector一样,在容器的中间删除插入元素,效率较低。
(2)、不同于vector,deque可在两端高效的执行删除和插入操作。
(3)、与vector一样而不同于list,deque支持对所有元素的随机访问。
(4)、在deque的两端插入元素不会使任何迭代器失效;在两端的删除使得指向被删元素的迭代器失效;在中间的任何位置的删除和插入使得所有迭代器失效。
16、String可视为字符串容器(连续存储),支持大多数顺序容器的操作,包括迭代器等(除不支持栈方式的操作,如pop back等)。(注意:char* ch=”aaaa”; string str(ch);// str=”aaaa”,不包括字符数组末尾的NULL)
17、顺序容器适配器:默认的stack和queue都基于deque实现; 而priority_queue则在vector基础上实现。 但每个适配斗提供了两个构造函数,一个默认构造函数即使得以默认的基础容器来构造该适配器,另外一个构造函数可传入一个顺序容器作为其第二个类型参数,从而制定其基础容器。适配器的实质是对底层基础容器的封装,提供新的操作接口,内部调用基础容器提供的接口。
如:stack<string> stk;//默认以deque实现;
Stack<string, vector<string> >;//指定了基础容器为vector。
stack/queue/priority_queue(其中queue/priority_queue都在同一个头文件#include<queue>)
18、各适配器的基础容器:Stack:vector/ list /deque,默认dequeQueue:lsit /deque,默认dequePriority_queue:vector /deque ,默认:vector
19、优先队列Priority_queue可为元素设置优先级,在插入新元素时,不是将其放在队列尾部,而是按优先级当到比他优先级低的元素的前面。可用<来比较他们的优先级。
第十章:关联容器
1、关联容器与顺序容器的本质区别在于,关联容器是按键key存储和读取元素且按key有序存放,而顺序容器则是按容器中的位置来访问元素,顺序至于加入容器的先后相关。
2、map存储key-value的pair<key,value>,key作为索引来访问其元素。
3、key仅包含键key而无value.主要支持某个键是否存在的访问。不支持下标操作,且由于元素为key,因此只能访问,不能修改。 应用:如黑名单。
4、mulitmap与mulitset与map和set类似,区别在于mulit_支持同一个键的多个实例,即容器中可存在多个相同key的元素,不支持下标操作。
5、pair类型:
pair<Type1,Type2> p(v1,v2);//构造给定值的 pairmake_pair(v1,v2);//以函数make_piar构造pair
6、map是key_value的集合,可理解为关联数组,以key作为下标来访问元素。如:
map<string,int> word_cnt;//记录单词的出现次数,空
word_cnt["C++Primer"]=2;//注意:以下标访问时,如果该key不存在,则会自动加入该key的一个元素,并将其value赋值为给定值。
而vactor则不能以下标来访问不存在的元素。
7、map的迭代器指向容器中的一个键值对pair,其中pair的key为const对象,只能修改其value。
8、mulitmap与mulitset的删除函数erase只带一个参数版本的,将会删除容器中该key的所有元素,并返回删除的个数,而带迭代器的则只会删除其指定的那一个元素。
9、mulitmap与mulitset中同一key的元素,存储在相邻位置,遍历时可保证依次返回相同key的元素。因此count(key)返回该key的元素个数,而find(key)则返回该key的第一个函数。
以下给出一个应用map容器的简单实例:读取一个文件,记录文件中每个单词出现的次数,并按字典顺序输出出现的单词和对应的次数
#include <iostream> #include <string> #include <map> #include <fstream> #include <sstream> using namespace std; int main() { ifstream ifile; string filename; cout<<"input filename: "<<endl; //filename="ifile.txt"; cin>>filename; ifile.open(filename.c_str()); if(!ifile) { cout<<"open file failed!"; return -1; } map<string,int> word_cnt; string str; string word; while(getline(ifile,str))//按行读文件,并保存 { istringstream iss(str); while(iss>>word) //将该按单词分解,并记录其出现的次数 ++word_cnt[word]; } map<string,int>::const_iterator mit=word_cnt.begin(); /*按字典顺序输出每个单词出现的次数(即map字典按key排序)*/ for(;mit!=word_cnt.end();++mit) { string temp(" time"); if(mit->second>1) temp+="s"; cout<<mit->first<<" occurs : " <<mit->second<<temp<<endl; } return 0; }
原文地址:http://blog.csdn.net/yuyixinye/article/details/44916335