容器
序列式容器
他们的排列顺序和输入的顺序一致,STL中有三个常用序列式容器:vector
,deque
,list
;
vector
允许随机存取,也就是可以直接利用索引进行存取任何元素,但在头部和中部进行存取较为耗时,优势是在尾部附加元素或者移除元素效率极高,实现如:
#include<iostream>
#include<vector>//头文件
using namespace std;
int main()
{
vector<int> arry;//空容器
for(int i = 0;i <= 6;i ++)
arry.push_back(i);
for(int i = 0;i < arry.size();i++)
cout<< arry[i]<<" ";
return 0;
}
其中size()
为序列式容器共有的函数;
可以通过[ ]
下标俩存取指定元素;
deque
即所谓的双向队列,在尾部和头部插入元素效率极高,这是他的优势,而不足在于在中间插入元素耗时长,实现如:
#include<iostream>
#include<deque>//头文件
using namespace std;
int main()
{
deque<int> arry;//空容器
for(int i = 0;i <= 6;i ++){
arry.push_back(i);
arry.push_front(i);
}
for(int i = 0;i < arry.size();i++)
cout<< arry[i]<<" ";
return 0;
}
其中push_front()
用于在队列头部插入元素;
list
即双向链表,优势在于在任何位置执行插入和删除效率极高,劣势在于随机存取不行;
#include<iostream>
#include<list>//头文件
using namespace std;
int main()
{
list<int> arry;//空容器
for(int i = 0;i <= 6;i ++)
arry.push_back(i);
while(!arry.empty()){
cout<< arry.front()<<" ";//输出第一个元素但不执行删除操作
arry.pop_front();//删除第一个元素但不返回被删除的元素
}
return 0;
}
关联式容器
关联式容器通常都是由二叉树实现,左子树的节点值都比父节点小,右节点值都比父节点值大。常见:set
,multiset
,map
,multimap
这四个容器。
set
set
的内部元素一句其值自动排序,每一个元素只能出现一次,不允许重复。
multiset
multiset
和set
类似,但是允许出现重复的值。
实现如:
#include<iostream>
#include<set>
using namespace std;
int main()
{
typedef set<int> intset;//缺省排列,默认operaotr<规则
intset arry;
arry.insert(1);
arry.insert(2);
arry.insert(3);
arry.insert(4);
arry.insert(5);
intset::const_iterator pos;
for(pos = arry.begin();pos != end.();++pos)
cout << *pos << " " ;
return 0;
}
所有关联容器都有insert
函数,提供元素插入功能。
但还要强调一下insert
函数,而在容器中其他用法:
- 在指定位置it前“插入”值为val的元素,返回指向这个元素的迭代器,
iterator insert( iterator it, const TYPE &val );
- 在指定位置it前“插入”num个值为val的元素
void insert( iterator it, size_type num, const TYPE &val );
- 在指定位置it前“插入”区间[start, end)的所有元素.
void insert( iterator it, input_iterator start, input_iterator end );
map
map
的元素是以一对数的形式存在,即(key,value)
,每一个元素都按照键值key
进行排序,并且每一个键值只允许出现一次。
multimap
multimap
和map
类似,但是允许键值重复。
实现如:
#include<iostream>
#include<map>
using namespace std;
int main()
{
typedef map<int,int> intmap;//缺省排列,默认operaotr<规则
intmaparry;
arry.insert(make_pair(1,1));
arry.insert(make_pair(4,6));
arry.insert(make_pair(2,4));
arry.insert(make_pair(7,1));
arry.insert(make_pair(6,9));
intmap::const_iterator pos;
for(pos = arry.begin();pos != end.();++pos)
cout << pos->second << " " ;
return 0;
}
其中make_pair
的功能就是生成(key,value)
元素;
其中内含指针first
指向键值,second
指向存的值。
当然map
容器,除了以上形式,还有一种直接赋值或者产生元素的形式,map可以是以operaator[ ]
,其中下标是键值,赋值的是存的值,也叫关联式数组,如:
#include<iostream>
#include<map>
using namespace std;
int main()
{
typedef map<int,int> intmap;//缺省排列,默认operaotr<规则
intmaparry;
arry[1] = 3;
arry[3] = 1;
arry[6] = 7;
intmap::const_iterator pos;
for(pos = arry.begin();pos != end.();++pos)
cout << pos->second << " " ;
return 0;
}
使用以上形式,值得一提的是我们当我们插入一个值如arry[10] = 1
但是map
容器中没有arry[10]
,此时会产生一个新的元素,加入容器中,即arry[10] = 1
;而mulltimap
容量不能使用,因为他会出现一对多的情况,即一个下标,对应多个存储值。
容器配接器
stack
,queue
,priority_queue
其中stack
容器遵循LIFO
原值,即后进先出,(栈)。
queue
普通队列,遵循FIFO
先入先出原值。
priority_queue
优先队列,元素优先权由排序准则决定,如operator<
即给一个按照从小到大的准则排列,赋予优先权即可。
迭代器
迭代器是一个可遍历STL
容器全部元素的对象,可以指向任何存在的位置,相当于c language
中的指针,但是呢,在STL里,我们不能以指针来看待迭代器,指针是与内存绑定的,而迭代器是与容器里的元素绑定的,删除了之后,该迭代器就失效了,在对其重新赋值之前,不能再访问此迭代器。
迭代器分为以下两类:
**双向迭代器:**双向迭代器可以双向进行,有list
,set
,multimap
,map
,multiset
的迭代器都是这类。
**随机存取迭代器:**可以进行随机访问。
常用于迭代器的操作的有以下内容:
operator *
:返回当前位置上的元素值;
operator ++
:将迭代器向后移动一位;
operator == and operator !=
判断迭代器是否指向同一个位置;
operator=
:为迭代器赋值,即给他一个位置指向,路标?
另外,与迭代器搭配的几个函数
begin()
:指向容器的起点;
end()
:指向容器的结束点,即最后一个元素的下一个位置;
判断容器是否为空时,除了前文介绍的empty(),size()
外,还有begin() == end()
相等时也是为空的。
而任何一个容器都有两种迭代器类型:
container::iterator
是可读可写模式,可以修改容器中的元素值;
container::const_iterator
是只读模式,不可修改容器中的元素值;
还需注意的是,在我们利用迭代器进行循环的时候,一般采用前置的递增++pos
,因为后置的还需要额外多一个临时对象,这个有一点的c++编程经历的同学应该都知道的,形如一下实现
container operarot++ (int)(){
container a(this);
++this;
return a;
}
当处理vector
,deque
时,当在一个循环中可能增加或移除元素时,要考虑到迭代器可能会失效的问题。
此外,还有一个reverse_iterator
即反向迭代器,常于rbegin()
,和rend()
搭配使用。