定义
容器:能够操作多种数据结构和算法的模板类和函数库。能够像现实中的容器一样存放各种类型的对象,一个容器中的所有对象必须是同一个类型的。
容器分为两大类:顺序容器、关联容器。
顺序容器
顺序容器有以下三种:vector(向量)、 deque(双队列)、list(列表)。
它们之所以被称为顺序容器,是因为元素在容器中的位置同元素的值无关,即容器不是排序的。将元素插入容器时,指定在什么位置(尾部、头部或中间某处)插入,元素就会位于什么位置。
1、vector
连续存储结构,每个元素在内存上是连续的;
支持高效的随机访问和在尾端插入/删除操作,但其他位置的插入/删除操作效率低下;
2、deque
连续存储结构,即其每个元素在内存上也是连续的,类似于vector,不同之处在于,deque提供了两级数组结构,第一级完全类似于vector,代表实际容器;另一级维护容器的首位地址。
这样,deque除了具有vector的所有功能外,还支持高效的首端插入/删除操作。
3、list
非连续存储结构,具有双链表结构,每个元素维护一对前向和后向指针,因此支持前向/后向遍历。
支持高效的随机插入/删除操作,但随机访问效率低下,且由于需要额外维护指针,开销也比较大。
顺序容器的选择:
a、若需要随机访问操作,则选择vector;
b、若已经知道需要存储元素的数目, 则选择vector;
c、若需要随机插入/删除(不仅仅在两端),则选择list
d、只有需要在首端进行插入/删除操作的时候,才选择deque,否则都选择vector。
e、若既需要随机插入/删除,又需要随机访问,则需要在vector与list间做个折中。
f、当要存储的是大型负责类对象时,list要优于vector;当然这时候也可以用vector来存储指向对象的指针,同样会取得较高的效率,但是指针的维护非常容易出错,因此不推荐使用。
注意:vector与deque的迭代器支持算术运算,list的迭代器只能进行++/–操作,不支持普通的算术运算。
关联容器
关联容器有以下四种:set(集合)、multiset(多重集合)、map(映射)、multimap(多重映射)。
关联容器内的元素是排序的。插入元素时,容器会按一定的排序规则将元素放到适当的位置上,因此插入元素时不能指定位置。
默认情况下,关联容器中的元素是从小到大排序(或按关键字从小到大排序)的,而且用<运算符比较元素或关键字大小。因为是排好序的,所以关联容器在查找时具有非常好的性能。
除了以上两类容器外,STL 还在两类容器的基础上屏蔽一部分功能,突出或增加另一部分功能,实现了三种容器适配器:stack(栈)、queue(队列)、priority_queue(优先级队列 )。
容器的函数
所有容器都有以下两个成员函数:
int size():返回容器对象中元素的个数。
bool empty():判断容器对象是否为空。
顺序容器和关联容器还有以下成员函数:
begin():返回指向容器中第一个元素的迭代器。
end():返回指向容器中最后一个元素后面的位置的迭代器。
rbegin():返回指向容器中最后一个元素的反向迭代器。
rend():返回指向容器中第一个元素前面的位置的反向迭代器。
erase(…):从容器中删除一个或几个元素。
clear():从容器中删除所有元素。
如果一个容器是空的,则 begin() 和 end() 的返回值相等,rbegin() 和 rend() 的返回值也相等。
顺序容器还有以下常用成员函数:
front():返回容器中第一个元素的引用。
back():返回容器中最后一个元素的引用。
push_back():在容器末尾增加新元素。
pop_back():删除容器末尾的元素。
insert(…):插入一个或多个元素。该函数参数较复杂,此处省略。
示例
(这里只列举一些容器以及一些函数用法)
顺序容器:
vector 容器
void main() //遍历、删除、插入
{
vector<int> v1;
v1.push_back(10); //copy 到申请的容器
v1.push_back(20);
v1.push_back(30);
//访问容器,定义一个迭代器: 相当于一个指针
//正向遍历
for(vector<int>::iterator it = v1.begin();it != v1.end();it++)
{
cout<<*it<<endl;
}
//逆向遍历
for(vector<int>::reverse_iterator rit = v1.rbegin();rit != v1.rend();rit++)
{
cout<<*rit<<endl;
}
//区间删除
v1.erase(v1.begin(),v1.begin()+2);
//指定位置删除
v1.erase(v1.begin());
//遍历删除
for(vector<int>::iterator dit = v1.begin();dit != v1.end();)
{
if(*dit == 2)
{
v1.erase(dit); //当删除迭代器所指向元素时,erase让it自下移
}
else
{
dit++;
}
}
//插入元素
v1.insert (v1.begin(),100); //头部插入数值100
v1.insert (v1.end (),200); //尾部插入数值200
return;
}
deque 容器
void printd(deque<int> &d)
{
for(deque<int>::iterator it = d.begin(); it != d.end();it++)
{
cout<<"元素"<<*it<<endl;
}
}
void main()
{
deque<int> d;
d.push_back(1); //在容器末尾增加新元素
d.push_back(2);
d.push_front(3); //在容器头尾增加新元素
d.push_front(4);
printd(d);
deque<int>::iterator it = find(d.begin(),d.end(),3); //查找指定元素3 找到时,返回该元素的迭代器;找不到时,返回end()。
if(it != d.end())
{
cout<<"3与第一个元素的距离为:"<<distance(d.begin (),it)<<endl;
}
}
关联容器:
set容器
void main()
{
set<int> set1;
//循环插入
for(int i = 0;i < 3;i ++)
{
int tmp = rand() % 5;
set1.insert(tmp);
}
//遍历打印集合
for(set<int>::iterator it = set1.begin();it != set1.end(); it++)
{
cout<<*it<<endl;
}
//删除集合
while(!set1.empty())
{
set<int>::iterator item = set1.begin();
set1.erase(item);
}
return;
}
map容器
//元素的添加、遍历、删除等基本操作
void main()
{
//1、创建map对象
map<int, string> map1;
//方法1 添加元素 pair是一个有两个元素的结构体,方便使用,类似map :键值可以随意使用
//pair可以用来当做map的键值来插入 pair<T1,T2> p1 创建一个空的pair对象,有两个元素T1和T2,采用值初始化
map1.insert(pair<int, string>(1,"hehe"));
map1.insert(pair<int, string>(2,"xixi"));
//方法2 添加元素 make_pair
//make_pair
map1.insert(make_pair(3,"haha"));
map1.insert(make_pair(4,"huhu"));
//方法3 添加元素
map1.insert(map<int, string>::value_type(5,"kaka"));
map1.insert(map<int, string>::value_type(6,"yiyi"));
//方法4 数组方式插入数据
map1[7] = "yaya";
//容器遍历(迭代器)
for(map<int, string>::iterator it = map1.begin();it != map1.end(); it++)
{
cout<<it->first<<"\t"<<it->second <<endl;
}
cout<<"遍历结束"<<endl;
//容器的删除
while(!map1.empty())
{
map<int, string>::iterator it = map1.begin();
map1.erase(it);
}
//map查找
map<int, string>::iterator it1 = map1.find(2);
if(it1 != map1.end())
{
cout<<"不存在"<<endl;
}
else
{
cout<<it1->first<<"\t"<<it1->second<<endl;
}
}