1、关联容器和顺序容器
C++中有两种类型的容器:顺序容器和关联容器,顺序容器主要有:vector、list、deque等。关联容器主要有map和set。如下图:
1、vector基本使用

#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <vector> using namespace std; //利用模版进行输出 template <typename T> void print(vector<T> a) { //输出方法1 for(auto i:a) { cout<<i<<'\t'; } cout<<endl; //输出方法2 typename vector<T>::iterator it;//前面要加typename,要不会出错 for(it=a.begin();it!=a.end();it++) { cout<<*it<<'\t'; } cout<<endl; //输出方法3,这里只是想说这样也可以输出 cout<<a[0]<<'\t'<<a[1]<<'\t'<<a[2]<<'\t'<<a[3]<<'\t'<<a[4]<<endl; cout<<"********************"<<endl; } int main() { /*vector初始化对象*/ vector<int> v1;//v1是一个空的vector,潜在的元素是int类型,执行时,默认初始化 v1={1,2,3,4,5}; print(v1); vector<int> v2(v1);//相当于vector<int> v2=v1 print(v2); vector<char> v3(5,'a');//v3中含有5个a字符 print(v3); vector<string> v4{"aa","ss","dd","ff","gg"};//v4赋值 print(v4); vector<float> v5(5);//出事化v5,为5个0.0 v5[0]=1.1; // v5[6]=8.8; vector可以利用下标访问,但是不能使用下标添加元素 print(v5); /*-------------------------------------------------------------------------------*/ /*vector操作*/ vector<string> v6; if(v6.empty())//vector是否为空 { cout<<"------"<<"v6 is empty"<<"-------"<<endl; } string s="qwe"; for(int i=0;i<5;i++) { v6.push_back(s);//末尾添加一个元素 } v6.pop_back();//末尾删除一个 v6.push_back("1234"); print(v6); cout<<"------"<<"v6的长度为:"<<v6.size()<<"------"<<endl; v6=v4;//拷贝v4中的元素赋值到v6中 if(v6==v4) { cout<<"------"<<"v6==v4"<<"------"<<endl; } /*-------------------------------------------------------------------------------*/ /*vector常用操作*/ vector<int> array={1,6,2,6,3,6,4,6,5,6}; array.erase(remove(array.begin(),array.end(),6),array.end());//需添加头文件algorithm /*remove函数使用: *remove(始地址,终地址,需要移除的元素),返回是被替换的数第一个数的地址,比如本题vector *原始数组为:[1,6,2,6,3,6,4,6,5,6],使用remove函数后为[1,2,3,4,5,6,4,6,5,6], *返回的地址为位置5上(0开始)的6的地址,如下输出数字5. cout<<*(remove(array.begin(),array.end(),6)-1)<<endl;*/ /*删除6的另一种方法 vector<int>::iterator it1; it1=array.begin(); for(it1=array.begin();it1!=array.end();it1++) { if(6==*it1) { array.erase(it1);//删除掉it1时,it1会指向下一个数,也就是6,然后再自加会指向下一个6,也就是邻接的6是删除不掉的 it1--;//加上这一句就不会出错 } }*/ print(array); vector< vector<int> > intVV;//vector实现二维数组 vector<int> intV; int i,j; for(i=0;i<3;++i){ intV.clear(); for(j=0;j<5;++j) intV.push_back(i*10+j); intVV.push_back(intV); } for(i=0;i<3;++i){ for(j=0;j<5;++j) cout<<intVV[i][j]<<'\t'; cout<<endl; } return 0; }
2、list基本使用
Lst1.assign() 给list赋值
Lst1.back() 返回最后一个元素
Lst1.begin() 返回指向第一个元素的迭代器
Lst1.clear() 删除所有元素
Lst1.empty() 如果list是空的则返回true
Lst1.end() 返回末尾的迭代器
Lst1.erase() 删除一个元素
Lst1.front() 返回第一个元素
Lst1.insert() 插入一个元素到list中
Lst1.pop_back() 删除最后一个元素
Lst1.pop_front() 删除第一个元素
Lst1.push_back() 在list的末尾添加一个元素
Lst1.push_front() 在list的头部添加一个元素
Lst1.rbegin() 返回指向第一个元素的逆向迭代器
Lst1.remove() 从list删除元素
Lst1.rend() 指向list末尾的逆向迭代器
Lst1.reverse() 把list的元素倒转
Lst1.size() 返回list中的元素个数
Lst1.sort() 给list排序
Lst1.unique() 删除list中重复的元素

#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <list> using namespace std; //利用模版进行输出 template <typename T> void print(list<T> a) { //输出方法1 for(auto i:a) { cout<<i<<'\t'; } cout<<endl; //输出方法2 typename list<T>::iterator it;//前面要加typename,要不会出错 for(it=a.begin();it!=a.end();it++) { cout<<*it<<'\t'; } cout<<endl; cout<<"********************"<<endl; } int main() { /*list初始化*/ list<int> l1;//定义一个空的list list<int> l2(5,1);//定以一个长度为5的list print(l2); list<char> l3={'a','b','c','d'}; print(l3); list<char> l4(l3);//相当于l4=l3 print(l4); list<char> l5(l3.begin(),l3.end());//同上 print(l5); list<char> l6=l5;//同上 print(l6); /*----------------------------------------------------------------------*/ /*常用操作*/ list<int> array={6,5,4,3,2,1,7}; print(array); array.sort(); print(array); array.reverse(); print(array); cout<<"返回第一个元素:"<<array.front()<<endl; cout<<"返回最后一个元素:"<<array.back()<<endl; cout<<"返回第一个元素迭代器:"<<*(array.begin())<<endl; cout<<"返回最后一个元素迭代器:"<<*(--array.end())<<endl; cout<<"返回第一个元素的逆向迭代器:"<<*(array.rbegin())<<endl; cout<<"返回最后一个元素的逆向迭代器:"<<*(array.rend())<<endl; list<int> array1; array1.assign(array.begin(),array.end());//给list赋值给array1 array1.pop_front();//删除第一个元素 array1.pop_back();//删除最后一个元素 print(array1); array1.clear();//删除所有元素 if(array1.empty())//判断lsit是否为空 { cout<<"array1 is empty"<<endl; } array1.assign(6,1);//array1={1,1,1,1,1,1} array1.push_front(11);//在list头插入元素 array1.push_back(13);//在list尾插入元素 print(array1); array1.erase(array1.begin());//擦除list第一个数 array1.erase(--array1.end());//擦除list最后一个数 print(array1); cout<<"array1的长度为:"<<array1.size()<<endl;//array1的长度 array1.insert(++array1.begin(),3,9);//从位置1开始插入3个9 print(array1); array1.remove(9);//移除list中的所有元素9 print(array1); array1.unique();//移除list中重复元素 print(array1); return 0; }
3、deque基本使用

#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <deque> using namespace std; //利用模版进行输出 template <typename T> void print(deque<T> a) { //输出方法1 for(auto i:a) { cout<<i<<'\t'; } cout<<endl; //输出方法2 typename deque<T>::iterator it;//前面要加typename,要不会出错 for(it=a.begin();it!=a.end();it++) { cout<<*it<<'\t'; } cout<<endl; //输出方法3,这里只是想说这样也可以输出 cout<<a[0]<<'\t'<<a[1]<<'\t'<<a[2]<<'\t'<<a[3]<<'\t'<<a[4]<<endl; cout<<"********************"<<endl; } int main() { /*deque初始化操作*/ deque<int> d1(10); for(int i=0;i<8;i++) { d1[i]=i; } print(d1); deque<string> d2(6,"abc");//d2中存在6个abc print(d2); deque<string> d3(d2);//初始化d3=d2 print(d3); /*----------------------------------------------------------------------*/ /*deque基本操作*/ deque<int> array(6,10); array.push_front(1);//头部插入 array.push_back(2);//尾部插入 array.insert(array.begin()+1,9);//在位置1插入9 print(array); array.pop_front();//头部删除 array.pop_back();//尾部删除 print(array); cout<<"头元素:"<<array.front()<<'\t'<<"尾元素:"<<array.back()<<'\t'<<"大小:"<<array.size()<<endl; array.erase(++array.begin(),--array.end());//删除该区间内的元素 print(array); array.clear(); if(array.empty()) { cout<<"array is empty"<<endl; } return 0; }
4、set基本使用
begin()--返回指向第一个元素的迭代器
clear()--清除所有元素
count()--返回某个值元素的个数
empty()--如果集合为空,返回true
end()--返回指向最后一个元素的迭代器
equal_range()--返回集合中与给定值相等的上下限的两个迭代器
erase()--删除集合中的元素
find()--返回一个指向被查找到元素的迭代器
get_allocator()--返回集合的分配器
insert()--在集合中插入元素
lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器
key_comp()--返回一个用于元素间值比较的函数
max_size()--返回集合能容纳的元素的最大限值
rbegin()--返回指向集合中最后一个元素的反向迭代器
rend()--返回指向集合中第一个元素的反向迭代器
size()--集合中元素的数目
swap()--交换两个集合变量
upper_bound()--返回大于某个值元素的迭代器
value_comp()--返回一个用于比较元素间的值的函数

#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <set> using namespace std; //利用模版进行输出 template <typename T> void print(set<T> a) { //输出方法1 for(auto i:a) { cout<<i<<'\t'; } cout<<endl; //输出方法2 typename set<T>::iterator it;//前面要加typename,要不会出错 for(it=a.begin();it!=a.end();it++) { cout<<*it<<'\t'; } cout<<endl; cout<<"********************"<<endl; } int main() { /*set初始化操作*/ set<int> s={11,12,14,15,15};//注意set里面不会存在重复的数 print(s); set<int> s1(s);//s1=s; print(s1); /*----------------------------------------------------------------------*/ /*set基本操作*/ s1.insert(16);//插入一个元素 int a[]={110,17,18,19}; s1.insert(a,a+3);//将a的前3个元素插入set print(s1); cout<<"s1的长度:"<<s1.size()<<'\t' <<"s1的第一个元素:"<<*s1.begin()<<'\t' <<"s1的最后一个元素:"<<*--s1.end()<<'\t'<<'\n'//注意最后位置要减1 <<"s1的最后一个元素:"<<*s1.rbegin()<<'\t' <<"s1的第一个元素:"<<*--s1.rend()<<'\t'//注意最后位置要减1 <<endl; cout<<"s1中11出现的次数是 :"<<s.count(11)<<endl;//因为set保证元素唯一,所以可以判断数据的存在性 cout<<"s1中第一个大于等于17的数是:"<<*s1.lower_bound(17)<<endl; cout<<"s1中第一个大于17的数是:"<<*s1.upper_bound(17)<<endl; pair<set<int>::const_iterator,set<int>::const_iterator> p; p = s.equal_range(14); cout<<"第一个大于等于14的数是 :"<<*p.first<<'\t' <<"第一个大于14的数是 : "<<*p.second<<endl; set<string> s2={"as","ad","af","ag","ah"}; print(s2); s2.erase(s2.begin());//删除第一个元素 s2.erase("ad");//删除对应元素 print(s2); s2.erase(++s2.begin(),--s2.end());//删除该区间内元素 print(s2); set<string>::iterator iter=s2.find("as");//找到 as 并返回该元素的位置 cout<<*iter<<endl; s2.clear(); if(s2.empty()) { cout<<"s2 is empty"<<endl; } return 0; }
5、栈、队列的使用
栈:
empty() 堆栈为空则返回真
pop() 移除栈顶元素
push() 在栈顶增加元素
size() 返回栈中元素数目
top() 返回栈顶元素

#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <stack> #include <deque> #include <vector> #include <list> using namespace std; //利用模版进行输出 template <typename T> void print(stack<T> a) { while(!a.empty()) { cout<<a.top()<<'\t'; a.pop();//元素出栈 } } int main() { /*stack的操作*/ stack<int> s; for(int i=0;i<5;i++) { s.push(i);//元素进栈 } cout<<"s的大小为:"<<s.size()<<endl; cout<<"s为:\n"; print(s); cout<<endl; deque<int> d(5,7); stack<int> s1(d);//将deque赋值给stack cout<<"s1为:\n"; print(s1); cout<<endl; vector<string> v={"aa","ss","dd","ff"}; stack<string,vector<string> >s2(v);//将vector赋值给stack cout<<"s2为:\n"; while(!s2.empty()) { cout<<s2.top()<<'\t'; s2.pop();//元素出栈 } cout<<endl; list<char> c={'a','s','d','f','g','h'}; stack<char,list<char> > s3(c);//将list赋值给stack cout<<"s3为:\n"; while(!s3.empty()) { cout<<s3.top()<<'\t'; s3.pop();//元素出栈 } cout<<endl; return 0; }
队列和栈的基本操作差不多

#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <queue> #include <deque> #include <vector> #include <list> using namespace std; //利用模版进行输出 template <typename T> void print(queue<T> a) { while(!a.empty()) { cout<<a.front()<<'\t'; a.pop();//元素出栈 } } int main() { /*queue的操作*/ queue<int> s; for(int i=0;i<5;i++) { s.push(i);//元素进栈 } cout<<"s的大小为:"<<s.size()<<endl; print(s); cout<<endl; deque<int> d(5,7); queue<int> s1(d);//将deque赋值给stack cout<<"s1为:\n"; print(s1); cout<<endl; vector<string> v={"aa","ss","dd","ff","hh"}; queue<string,vector<string> >s2(v);//将vector赋值给stack cout<<s2.front()<<'\t'<<s2.back()<<endl; list<char> c={'a','s','d','f','g','h'}; queue<char,list<char> > s3(c);//将list赋值给stack cout<<"s3为:\n"; while(!s3.empty()) { cout<<s3.front()<<'\t'; s3.pop();//元素出栈 } cout<<endl; return 0; }
6、Map的基本使用
Map主要用于资料一对一映射(one-to-one)的情况,map内部的实现自建一颗红黑树,这颗树具有对数据自动排序的功能。
begin() 返回指向map头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数
empty() 如果map为空则返回true
end() 返回指向map末尾的迭代器
equal_range() 返回特殊条目的迭代器对
erase() 删除一个元素
find() 查找一个元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比较元素key的函数
lower_bound() 返回键值>=给定元素的第一个位置
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
size() 返回map中元素的个数
swap() 交换两个map
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数

#include <iostream> #include <stdlib.h> #include <string.h> #include <algorithm> #include <map> #include <deque> #include <vector> #include <list> using namespace std; //利用模版进行输出 template <typename T> void print(map<T,T> a) { cout<<"输出的方法1:\n"; typename map<T, T>::iterator it; for(it = a.begin(); it != a.end(); it++) cout<<it->first<<' '<<it->second<<endl; cout<<"输出的方法2:\n"; typename map<T, T>::reverse_iterator iter; for(iter = a.rbegin(); iter != a.rend(); iter++) cout<<iter->first<<' '<<iter->second<<endl; } int main() { /*map的赋值操作*/ map<string, string> m; //赋值的方法1 m.insert(map<string, string>::value_type ("001", "s1")); m.insert(map<string, string>::value_type ("002", "s2")); m.insert(map<string, string>::value_type ("003", "s3")); //赋值方法2 m.insert(pair<string,string>("004","s4")); m.insert(pair<string,string>("005","s5")); m.insert(pair<string,string>("006","s6")); print(m); cout<<"--------------------------------------------"<<endl; map<int, string> m2; //赋值的方法3 m2[1]="one"; m2[2]="two"; m2[3]="three"; // print(m2); 这里两个类型不一样不能进行模版输出 map<int, string>::iterator iter2; for(iter2 = m2.begin(); iter2 != m2.end(); iter2++) cout<<iter2->first<<' '<<iter2->second<<endl; for(int i=1;i<=3;i++)//这种输出必须保证map中前一个数为int类型 { cout<<m2[i]<<endl; } cout<<"--------------------------------------------"<<endl; /*判断插入是否成功*/ map<char,char> m3; m3.insert(map<char,char>::value_type('1','a')); m3.insert(map<char,char>::value_type('2','b')); m3.insert(map<char,char>::value_type('3','c')); m3.insert(map<char,char>::value_type('4','e')); m3.insert(map<char,char>::value_type('5','f')); m3.insert(map<char,char>::value_type('6','g')); pair<map<char,char>::iterator,bool> insert_pair;//接收判断插入的成功与否 insert_pair=m3.insert(pair<char,char>('4','d')); if(insert_pair.second) cout<<"插入成功!"<<endl; else cout<<"插入失败!"<<endl; insert_pair=m3.insert(pair<char,char>('4','d')); if(insert_pair.second) cout<<"插入成功!"<<endl; else cout<<"插入失败!"<<endl; print(m3); cout<<"--------------------------------------------"<<endl; cout<<"m3的大小为:"<<m3.size()<<endl; cout<<"--------------------------------------------"<<endl; /*数据查找*/ //1 map<char,char>::iterator iter=m3.find('2'); if(iter!=m3.end()) cout<<"2对应的值为"<<iter->second<<endl; //2 int n=m3.count('2'); if(n) cout<<"2存在于map中"<<endl; else cout<<"2不存在于map中"<<endl; //3 iter=m3.lower_bound('2'); cout<<"2对应的值为:"<<iter->second<<endl; iter=m3.upper_bound('2'); cout<<"2后面的键对应的值为:"<<iter->second<<endl; cout<<"--------------------------------------------"<<endl; /*数据删除*/ //1 iter=m3.find('2'); m3.erase(iter); //2 n=m3.erase('3'); if(n) cout<<"3以及对应的value删除成功"<<endl; else cout<<"3以及对应的value删除失败"<<endl; //3 m3.erase(++m3.begin(),--m3.end()); print(m3); }
容器选择的基本原则:
1、除非你有很多的理由选择其它的容器,否则应该用vector。
2、如果你的程序有很多小的元素,且空间的额外开销很重要,则不要使用list。
3、如果程序要求随机访问元素,则应该使用vector或则deque。
4、如果程序需要在容器的中间插入删除元素,应该使用list。
5、如果程序需要在容器的头尾位置插入或删除元素,但不会在中间位置进行插入或者删除操作,则使用deque。
6、如果程序只有在读取输入时才需要在容器中间位置插入元素,随后需要随机访问元素则:
首先,确定是否真的需要在容器中间位置添加元素,当处理输入数据时,通常可以很容易地向vector追加数据,然后调用标准库的sort函数来重排容器中的元素,从而避免在中间位置添加元素。
如果必须在中间位置插入元素,考虑在输入阶段使用list,一旦输入完成,将list中的内容拷贝到一个vector中。
注:如果不确定应该使用哪种容器,那么可以在程序中只使用vector和list公共的操作:使用迭代器,不使用下表操作,避免随机访问。这样。在必要的时候选择vector或list都很方便。