C++源码剖析与泛型编程(侯捷)(四) Deque、Queue和Stack深度探索

容器Deque

内存中是分段连续的缓冲区buffer,每次扩充时,扩充一个固定的 buffer 大小。

Deque的first指针指向一个buffer中的头,last指向同一个buffer的尾,node告诉控制中心map(vector实现,可不是map容器哦)的位置,cur指向当前元素,会随着++或者--变化。当然,如果跳到下一缓冲区,first和last自然也会变。另外还有两个start,finish迭代器分别指向头和尾。

map里指向的还是一串指针,因此map_pointer类型是T**。

模板参数中的 BufSiz 是指每个 buffer 容纳的元素个数,可自定。默认为0时,根据 sz[ sizeof(value_type) ] 的大小,

if sz < 512 则 buffersize = 512 / sz                           else  buffersize = 1

控制中心 map 是一个指针 指向一个指针的数组 vector  ,其扩充时也是两倍成长,次扩充后 copy 原有元素到新内存的中段,时前部和后部后空出,以便于增加 map 中 node 时的操作。

没有自己的sort方法,因此只能用::sort() STL模板函数。

template<class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
    typedef random_acess_iterator_tag iterator_category;
    typedef T value_type;
    typedef Ptr pointer;
    typedef Ref reference;
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef T** map_pointer;
    typedef __dequr_iterator self;
 
    T* cur;
    T* first;
    T* last;
    map_pointer node;       //指向map中的元素,即是一个指向指针的指针
....
};

在队列前后入队出队时,迭代器指向边界时,会自动修正++与--所指向的地址,有能力跳到下一个缓冲区,以保证表面上看是连续的

Deque的高明之处:deque<T>::insert()

选择较短的一段在最前端或者最尾端插入一个元素,然后再元素搬移,再对空的安插点设定新值。

deque如何模拟连续空间

主要实现思想就是定义迭代器的 + - = 等操作,要求能够检查边界,跳到另一个缓存区去

 operator-     去算start和finish之间夹了多少个元素=(node-x.node-1)*diffrence_type(bufsize)+cur-first+x.last-x.cur

++ 与 -- 的实现,基本都是由 后 ++ 调用 前 ++后 -- 调用 前 --

这里++不需要先判断的原因是因为last可以指向尾后指针,而first没有。

deque的指针是一种随机访问指针,所以应该支持 +n 操作,重载 += 与 + 操作。-= 可以利用 += 代码实现。

self& operator-= (difference_type n)
{ return *this += -n; }
 
self operator- (difference_type n) const
{
    self tmp = *this;
    return tmp -= n;
}
 
reference operator[] (difference_type n) const
{ return *(*this + n); }

 容器queue和stack

  • queue 和 stack 都是基于 deque 实现,(内含一个deque,并限制某些操作)技术上本质为容器适配器。
  • 因为只能先进先出或者先进后出,不允许遍历,所以不提供迭代器   (声明 iterator 时会报错)否则放元素就会破坏这个特性。

 

其中数据为默认类型为 deque 的容器 c,所有的对 queue 和 stack 的操作都是转调用 c 的类方法去做

本质上能完成这些转调用方法的容器都可以作为底层容器去实现 queue 】

queue不可以选择vector作为底部支撑的原因是因为vector没有pop。当然如果程序不会调用这个pop的话,编译自然也可以通过。

    list 和 deque 都可以作为底层容器实现 stack 和 queue。
    stack 可以选择 vector 作为底层结构,queue 不可选择 vector 作为底层结构。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值