STL list和deque

list:

list的内存空间是一个环状的双向链表,如图:

(请原谅我拙劣的画图)

为了保证容器迭代器范围为“前闭后开”的区间,end()迭代器所指的是空节点

list node的结构为:

template <class T>
struct __list_node{
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
}
不同于vector的连续线性空间,list的空间不保证是连续存在的

每次插入或者删除list的一个元素,就配置和释放一个元素空间,对任何位置的元素删除或插入操作都是常数时间

相比于vector这么做的好处是:

(1)在插入元素时,vector需要移动某块连续的空间,如果碰到空间不足的情况,vector还要经历开辟新空间→复制插入点前旧元素到新空间→在新空间插入新元素→复制插入点后面的旧元素到新空间→修改相关迭代器→释放旧空间等一系列操作,这么做不仅效率低下,还可能浪费新空间的剩余空间;而list在插入操作时,只需修改插入点的前后指针即可,并且不会出现大量复制元素的情况,对空间运用绝对的精准

(2)vector的插入操作有可能造成容器空间的重新配置,导致原有的迭代器全部失效;而list的insert和splice操作都不会造成原有的list迭代器失效,这是显而易见的,list的每个节点并非存储在连续空间,插入操作并不会影响它们在空间中的位置。


deque:

deque是一种双向开口的连续线性空间,所谓双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,而vector只是单向开口的连续空间,因为在其头部操作效率奇差,无法接受。

说deque是连续线性空间是从逻辑角度出发的,事实上deque的存储空间是分段连续的,如图:

deque采用一个类似于指针数组的map作为空间管理的主控,map中的每个元素又指向一段连续的空间,称为缓冲区。缓冲区才是真正存放数据的空间实体。deque迭代器:

template<class T,class Ref,class Ptr,size_t Bufsize>
struct __deque_iterator{
  ....
  T* cur;       //此迭代器所指缓冲区的现行元素
  T* first;    //此迭代器所指缓冲区的头
  T* last;      //此迭代器所指缓冲区的尾
  map_pointer node;//指向缓冲区在map中相应位置
}

deque的这种空间结构与二维数组十分相像,两者的最大区别是二维数组空间大小是固定的,不能生长,而deque作为序列式容器,必须要解决元素过多,空间不足的问题。

当deque中所有缓冲区填满后,为了存放新增元素,deque必须开辟一段新的缓冲区,并且新增的缓冲区地址必须添加到map中如果此时map中已无空余空间存放这个地址,那么只能申请一个更大的map,整个过程总结起来就是:

重换一个map→配置一个新缓冲区→复制旧缓冲区地址到新map中→将新缓冲区地址添加到新map中→将新元素添加到新缓冲区中

相比于vector在空间不够时的处理,deque不会改变元素在原来空间中的位置,也避免了拷贝元素等复杂操作,效率更高。


总结:无论是vector、list还是deque都属于序列式容器,序列式容器的一个特点就是要让使用者看起来元素在容器中都是连续存放的,而不用关心它们实际的存储空间;它们的迭代器必须提供递增、递减、取值与成员存取等操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值