和vector的差异:
1,双端开口--允许常数时间内对头端元素的插入/删除;
2,deque没有容量概念,因为它是动态以分段连续空间组合而成
不像vector那样”因为旧空间不足而重新配置一块更大空间,复制元素,释放空间“
deque:
1,一段一段的定量连续空间组成;
2,一旦在前端或尾端增加空间,配置一段定量连续空间,串接在整个deque的头或尾端;
3,在分段的定量连续空间上,维护整体连续的假象,
避开了‘重新配置,复制,释放’的轮回
4,map:连续空间,**T,指向另一个较大的连续空间,即缓冲区,缓冲区是dueue的主体,真正存放数据【缓冲区默认512B】实现:
1】 迭代器start 指向第一缓冲区的第一个元素
迭代器finish 指向最后缓冲区的最后一个元素(下一位置)
迭代器的结构
cur :指向缓冲区的现行元素;
first 指向缓冲区的头
last:指向缓冲区的尾
node:指向管控中心
2】 指向管控中心map的指针
map的大小
节点不足时----重新配置map的2个函数:
(1)reserve_map_at_back()
{if(nodes_to_add+1>map_size-(finish.node-map))map尾端节点备用空间不足
重换一个map
}
(2)reserve_map_at_back()
{if(nodes_to_add> (start.node-map))map前端节点备用空间不足
重换一个map
}
重换一个map:
1, 配置更大的空间(大小=原来大小+max(原来大小,需要的大小))
2, 拷贝原来的map内容
释放原来的map(之后调整start,finish指针的位置)
函数关系-辅助图:
3】 重要实现----内存管理
(1)缓冲区实际存储元素;
(2)map管控管理---缓冲区的释放,增加。
画图实现:
最终保留一个缓冲区,这是deque的初始状态
1】 对头尾以外的每一个缓冲区,析构元素+释放缓冲区内存
2】 至少有头尾缓冲区时,
头缓冲区的元素析构,
尾缓冲区的元素析构,
释放尾缓冲区(注意保留头缓冲区)
3】否则(只有一个缓冲区时)仅唯一缓冲区的元素析构(并不释放缓冲区空间)
1】 最后缓冲区有>=1个元素,调整指针==删除并析构最后元素
2】 否则进行缓冲区释放工作(释放最后一个缓冲区,调整finish的状态)
1】 第一缓冲区有>=2个元素,第一元素析构,调整指针start.cur
2】 否则释放缓冲区(第一缓冲区的第一个元素析构+释放缓冲区+调整指针start.first)
{
index=pos=start; 1】计算清除点之前的元素个数,
如果比较少(if(index<size()>>1)),则将清除点之前的元素后移
删除最前一个元素---pop_front();
2】否则(清除点之后的元素个数少)
将清除点后的元素前移
删除最后一个元素---pop_back()
}
1]if (first==start&&last==finish)清除区间是整个deque,直接用clear()
2]计算清除区间的长度,
3】如果清除区间前方的元素个数少----
copy_backward向后移动前方元素;
析构冗余元素;
释放缓冲区
1】 否则(清除区间后方的元素个数少-)
copy()向前移动后方元素
析构冗余元素;
释放缓冲区
1]如果插入点是最前端,
交给push_front做
2】如果插入点是最后端,
交给push_back做
2】 否则,交给insert_aux做
insert_aux:
1】 计算插入点之前的元素个数,index=pos-start
2】 计算插入点之前的元素个数少,那么插入点之前的元素前移
否则,插入点之后的元素后移
3】 插入点设置新值