STL源码剖析(十)序列式容器之deque

STL源码剖析(十)序列式容器之deque


前面我们说的vector是单向开口,而deque是双向开口,也就是保证常数时间在头部和尾部插入元素

一、deque的数据结构

我们先讨论deque是如何实现双向开口的,也就是可以双向增长?

deque是动态地通过分段连续的空间组成的,也就是说,deque可以随时分配一块内存,连接到原空间的前部或者后部。deque扩容并不会像vector一样,申请一段更大的空间,然后将数据拷贝过去,再释放原内存

deque为了管理这些分段连续的内存空间,使用了一个中控器,中控器是实际是一个指针数组,被使用的元素指向一段连续空间,如下所示

在这里插入图片描述

下面我们来看看deque的数据结构

template <class T, class Alloc = alloc, size_t BufSiz = 0> 
class deque {
  typedef T value_type;
    
  typedef value_type* pointer;
  typedef pointer* map_pointer;
  ...
      
  typedef __deque_iterator<T, T&, T*>                      iterator;
  ...
  
protected:                      // Data members
  /* 迭代器 */
  iterator start;
  iterator finish;

  /* 中控器 */
  map_pointer map;
  size_type map_size;

  ...
};

可以看到,deque中有一个mapmap_size,它们维护着deque的中控器。map其实是一个指针数组,其数组项为value_type*类型,指向一块连续的缓存区,map_size表示该数组项元素个数

另外还有两个迭代器startfinishstart指向首元素,finish指向最后一个元素的下一个元素

deque提供random_access_iterator_tag类型的迭代器,而deque内部并不是连续的内存,它只是对外连续,内部是分段连续,所以deque的迭代器为了实现这样的功能,较为复杂

deque内部的数据结构可以用以下图表示

在这里插入图片描述

还有一个问题就是,deque的每个缓存区有多大呢?

可以通过类模板中的BufSiz指定,默认情况下是512个字节

二、deque的迭代器

下面再来分析deque的迭代器,它实现的是一个random_access_iterator_tag类型的迭代器,而deque内部并不是连续的,所以它的实现较为复杂

它的定义如下

template <class T, class Ref, class Ptr>
struct __deque_iterator {
  /* 满足STL迭代器的设计规范 */
  typedef random_access_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;

  T* cur; //缓存区当前元素
  T* first; //缓存区开头
  T* last; //缓存区结尾
  map_pointer node; //指向中控器的一个节点
  
  ...
};

deque的迭代器中有四个变量,cur指向缓存区的当前元素,first指向缓存区开头,last指向缓存区结尾,node指向中控器的某个节点,如下图所示

在这里插入图片描述

所以begin和finish迭代器如下图所示

在这里插入图片描述

看完迭代器的数据结构,再来看看它的操作

operator++

self& operator++() {
    ++cur; //cur指针指向下一个
    if (cur == last) { //如果到缓存区结尾
        set_node(node + 1); //跳到下一个缓存器
        cur = first; //缓存区的第一个节点
    }
    
    return *this; //返回操作后的迭代器
}

首先cur指针指向下一个元素,如果到达缓存区的结尾,那么就跳到下一个缓存区,再指向该缓存区的第一个元素

set_node用于跳转缓存区,我们之后再讨论

operator–


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值