一个双向开口的逻辑上连续线性空间。

Vector 和 Deque 一般是可以放一起讨论的,但是实际上 Deque 的实现复杂比 Vector 难了…额不以万里计…

Deque 在头部和尾部都可以做到常数时间的插入和删除操作。

当然 Vector 也可以在头部进行插入和删除操作,但是这个速度嘛…自己体会。

Deque 相对于 Vector 来说,是没有容量(capacity)的概念的,因为它是由个数动态增长的分段空间组合而成的(这些空间在逻辑上是连续的),所以不会像Vector一样需要进行配置复制释放来完成增长。

Deque也提供了 Random Access Iterator(随机存取迭代器),但是它的迭代器并不是普通指针,其复杂度相比Vector来说,简直上天~恩…上天。

因此,除非必要的操作,我们应尽可能选用 Vector 而不是 Deque。

如果我们要对 Deque 进行排序操作,就先将 Deque 复制到一个 Vector 中,对 Vector 进行排序后,再复制回 Deque.

 

Deque的中控器:

Deque 在逻辑上来看是一段连续线性空间,实际上(物理上)则是由一段段的定量连续空间构成。

如果有必要在Deque的首部或者尾部增加一段新的空间的话,那就配置一段定量连续空间,然后串接在 Deque 的首部或者尾部即可。

Deque 采用了一小块所谓的map(这里指的并不是STL的容器,而是一个二级指针)作为主控,这里的map是一小块线性连续空间,每一个元素也都是一个指针,指向另一段连续线性空间的头部,我们称这段空间为缓冲区。这些缓冲区就是Deque的存储空间主体。

STL一般是允许指定缓冲区的大小的,默认0则表示用512byte大小的缓冲区。

样子嘛,还是上图把,这样比较明显:

Deque-map

 

Deque的大致情况我们了解了,接来下我们来我们来看看迭代器的设计。

Deque的迭代器:

我们知道,Deque是一个分段的逻辑连续空间,那么如何让这个空间看起来是连续的呢,就得靠与外界的接口迭代器来实现了。

所以其真正的任务是 operator++ 与 operator– 的设计。

那么Deque的迭代器应该具备什么能力呢,首先它要指出分段连续空间的位置(即缓冲区的位置),然后要能判断自己是否位于缓冲区的边缘,然后又要能够正确跳到下一个或者上一个缓冲区,于是必须掌控map。

采用了下面的实现方法:

下图可以很好地表示deque的中控器,迭代器,缓冲区之间的关系:

Deque-Iterator

下面是 Deque 迭代器的几个关键行为。由于迭代器内对各种指针的运算都进行了重载操作,所以各种指针运算如加、减、前进、后退都不能直观视之。

其中重点是:当行进到迭代器边缘时,要调用 set_node函数 跳一个缓冲区。

以下各个运算子的重载,则是Deque Iterator 成功运作的关键:

 

Deque的数据结构:

除了要维护map之外,也维护 start,finish两个迭代器,分别指向缓冲区第一个元素和最后一个元素的下一位置。

除此之外,还要知道map的大小。(一旦map大小不足则需要重新配置)

这样,有了上述结构,以下机能便能轻易完成:

 

deque的构造与内存管理:

来来来,看代码…反正每次侯捷大神都这样…

 

哔~…太复杂了…恩不爆粗…2016.7.19 记于此…留待后观。

【STL】Deque
Tagged on:
0 0 投票数
Article Rating
订阅评论
提醒

0 评论
内联反馈
查看所有评论