1.STL的三种类型容器
顺序容器:
vector 向量容器
deque 双端队列
list 链表
容器适配器:
stack 栈
queue 队列
priority_queue 优先级队列
关联容器:
set/multiset 集合
map/multimap 映射表
2.各容器的底层实现
具体实现请参考侯捷的《STL源码剖析》,此处不贴源码,只是对底层实现做简单介绍。
顺序容器:
<1>vector 向量容器
vector底层是动态开辟的可2倍自增长的一维数组,默认不申请空间。
第一次向vector中增加元素时,开辟一个格子,以后如果内存不足,每次扩大2倍。因此,这种数据结构在刚开始内存增长时的效率很低。vector底层内存连续。
<2>deque 双端队列容器
deque底层时动态开辟的一维可2倍自增长的二维数组,默认部申请空间。deque底层内存不连续。
第一次向deque中增加元素时,一维开辟两个格子,二维开辟的元素个数遵守以下规则:如果变量的类型<4096,开辟4096/sizeof(_Ty)个格子;否则开辟一个格子,格子大小为sizeof(_Ty)。size=sizeof(_Ty) < 4096 ? 4096/sizeof(_Ty) : sizeof(_Ty);
因为是双端队列,所以底层有两个指针(_start和_finish)。_start和_finish都向最中间。头插时,_start向上移动,尾插时,_finish向下移动。二维数组不够用时,再开辟二维空间。如果二维已经开辟满了,则一维成2倍增长(cur *= 2),并将二维空间移动到新的一维空间的最中间,减少push_front和push_back时,开辟内存和移动的次数(pos = cur/2 -1)。
<3>list
list的底层是双向链表。对list的操作就是对链表的操作,所以list容器的添加和修改效率很高。list默认分配一个头节点,在插入值的时候,动态的申请节点,挂在链表中。
容器适配器:
容器适配器底层没有自己的数据结构,他们是对某种容器的代理。
<1>stack默认的底层数据结构是deque
<2>queue默认的底层结构是queue
<3>priority_queue默认的底层结构是用vector实现的大根堆
关联容器:
关联容器的底层是RBtree,key有序排列。对关联容器的操作都是对红黑树的操作。插入元素时,最多调整2次;删除元素时,最多调整3次。
set/multiset只保存key,set中key不能重复,multiset中key可以重复
map/multimap保存的是key-value,map中key不能重复,multimap中key可以重复
Boost库中实现了hash_map和multimap,是用链地址法实现的哈希表,链表的每个元素保存的都是键值对。
3.各类型容器的操作接口函数
<1>vector
定义:vector<int> vec;
插入:vec.push_back(value); vec.insert(it, value);
删除:vec.erase(it); vec.erase(vec.begin(), vec.end());
获取首元素:vector::itreator it = vec.begin();
vector末尾后一个元素:vector::iterator it = vec.end();
迭代器运算:it++; it–; ++it; –it;
vector的reserver方法和resize的区别:
vec.reserver(size);//只开辟内存
vec.resize(size);//开辟空间并构建size个对象
<2>deque
定义:deque<int> dq;
插入:dq.push_front(value); dq.push_back(value); dq.insert(it,value);
删除:dq.erase(it); dq.erase(dq.begin(), dq.end());
获取首元素:deque::itreator it = dq.begin();
deque末尾后一个元素:deque:;iterator it = dq.end();
迭代器运算:it++; it–; ++it; –it;
<3>list
定义:list <int> list1;
插入:list1.push_front(value); list1.push_front(value); list1.insert(it, value);
删除:list1.erase(it); list1.erase(list1.begin(), list2.end());
切片函数:list.splice(list.begin(), list.end(), list2, list2.end());
//将list1从begin到end的节点都拼接到l