简介

deque是double ended queue(即双端队列)的简称。 就像C++中的大部分容器的一样,deque具有以下属性:

  • 顺序的(sequence)
  • 动态增长的(dynamic growing)
  • 自定义内存分配的(allocator-aware)

动态内存分配

容器的顺序性(或序列性)和内存分配器我们留到以后再说,这里我们先来探讨下容器的动态增长需求所带来的动态内存分配性质。

动态内存分配在这里的意思是容器的大小会随着需要而增长,这经常伴随着一些内存需求性的操作而发生(例如insert操作,插入一个元素势必需要为这个元素预留内存空间,不然它会成为一个无处息身的流浪狗-^-)。 每个容器都有其实际上的容量(capacity),当容量耗尽,没有多余的空间时,就需要为这个容器动态地增长(正方形单元表示内存单元,深色表示已使用,白色表示未使用):

之所以称之为动态,是因为这个操作发生在运行时。

扩大因子

这里就涉及到resize factor, 也就是重新分配内存时应该分配的内存大小问题。 分配因子太小很可能会造成后续频繁的内存分配需求,因为当前剩下的内存太少;太大又可能造成内存浪费(尤其是当原内存本身就很大时)

sgi stl的扩大因子好像是2(即新的内存大小是原内存的2倍),但有研究指出值为1.5的factor在实际中似乎拥有更好的效果。

实现

在实现上,容器内存的动态增长本质上由以下几步完成:

  1. 分配一块更大的内存空间
  2. 释放之前的内存(在完成内容复制之后)
  3. 替换为新的内存空间

解决的问题

用过C语言的人都知道,C代码中充斥着各种各样的静态内存分配,大部分都以数组的形式出现:

char buffer[1024] = {0};

然而,使用静态内存会带来很多问题:

  • 第一,硬编码,降低了代码的可读性, 看的人根本不知道1024意味着什么。 还好,1024还算是比较典型的数字。但如果换成23、33这些数字,天啊,我完全不知道这些数字是不是有着特殊的含义(你还真别说,有些奇怪的数字还真是特殊考虑过的)!嗯,我们戏称这些数字为魔数(magic number)。
  • 第二,内存利用率。 你分配了很大一块内存,但实际上只使用了很小的一部分。什么?为什么不分配的小一点?哈哈,因为我也不知道到底要分配多大。
  • 第三,静态内存不可增长。 当你知道之前定义的内存大小根本不够用的时候怎么办呢?哦,我可以再定义一个足够大的内存或者把之前的数组大小改得大一些。 那要是这种情况发生在代码运行时呢?
  • 第四,降低工作效率。 处理以上这些琐碎而简单的问题真是让我操碎了神,更烦人的是到处都是这些问题。

如果有那么一种机制,让我在调用各种插入、串接操作时都不用考虑这些问题就好了。 不用想了,那就是动态内存分配!! 动态内存分配的重要性对于C++来说,就像是Garbage Collector对于Java那样重要!

双端队列

好了,言归正传。 实际上,deque想要实现的是一种概念----双端队列。 它是一种LIFO (last in first out)队列,具有以下特性:

  • 双端,即头端和尾端
  • 每个端口都支持入队出队操作

双端

双端分别是头端和尾端,在deque类中对应frontback字样。 带有这两个字样的操作,也即成员函数,都是与端口相关的。

至于为什么采用这两个名称,而不采用诸如headPort、tailPort这样的,我猜想是为了保持各个容器接口之间的一致性与简洁性, 便于记忆。 因为有很多容器都具有 第一个 元素和 最后一个 元素这两个通用概念,front和back刚好对应了它们。 同时,front和back也在一定程度上反映了容器的方向与位置信息,适合用来投射概念上的东西(例如双向链表和双端队列)。

入队和出队

入队、出队操作分别为带有push、pop操作,道理与双端概念大致相似,这里不再赘述。

但这两个操作非常重要的一点就是----不管是在头端还是尾端,时间复杂度都是O(1),即常数时间。

双端队列接口

  • push_back
  • push_front
  • pop_back
  • pop_front

其他接口

理论与实践总是会有不小的距离,容器在实际使用中的易用性有时候更重要。 所以deque类提供的接口远远不止理论上的那几个, 还包括普遍出现在其它容器中的一些接口。 例如Iterator系列、插入、swap、clear等。

C++ 头文件系列(deque)的更多相关文章

  1. C++ 头文件系列(array)

    注意,该头文件仅在C++11中标准才开始出现. 简介 与语言内置的数组一样, array类模版支持几乎所有内置数组包含的特性: 顺序的(sequence) 内存连续的(contiguous stora ...

  2. C++ 头文件系列(queue)

    简介 这个头文件定义了两个跟队列有关的类----quque.priority_queue,分别实现的是队列 和 优先队列这两个概念. 但是与这两个类模版与其它类模版(vector.array等)最大的 ...

  3. C++ 头文件系列(stack)

    简介 该头文件只含有一个类模版stack, 它实现栈的概念,是一个容器适配器(说实话,在写这篇随笔之前我都不知道有这么个类模版). 栈 栈只有一个重要的特性: LIFO(last-in first-o ...

  4. C++ 头文件系列(vector)

    简介 vector头文件包含vector的类模版以及该模版的显示特化版本vector< bool >. vector是C++容器库中非常通用的一种容器,如果你不知道该决定使用哪一种容器,或 ...

  5. C++ 头文件系列(map)

    简介 该头文件包含两个概念相似的容器----map.multimap. 而这两个容器反映的概念就是 映射. 这两个容器 相同 的属性有: 关联性 映射 动态增长 键(Key)唯一性 这两个不相同的属性 ...

  6. C++ 头文件系列(unordered_map、unordered_set)

    简介 很明显,这两个头文件分别是map.set头文件对应的unordered版本. 所以它们有一个重要的性质就是: 乱序 如何乱序 这个unorder暗示着,这两个头文件中类的底层实现----Hash ...

  7. C++ 头文件系列(iterator)

    简介 该头文件围绕迭代器展开,定义了一系列与迭代器有关的概念,但最最最重要的一点就是----它和其它容器一起实现了C++容器的Iterator设计模式. Iterators are a general ...

  8. C++ 头文件系列 (algorithm)

    简介 algorithm头文件是C++的标准算法库,它主要应用在容器上. 因为所有的算法都是通过迭代器进行操作的,所以算法的运算实际上是和具体的数据结构相分离的 ,也就是说,具有低耦合性. 因此,任何 ...

  9. C++ 头文件系列 (bitset)

    简介 该头文件有关位集,实际上是vector 位 位本质上对应bool的概念,只有0或1,true或false两种对立的值. 但很可惜,字节才是机器上最小的存储单元,所以bool基本上是由一个字节大小 ...

随机推荐

  1. web.xml运行序列总结

    在整个订单<context-param>--<listener>--<filter>--<servlet>. 其中,内的各类别中的序列被运行.和< ...

  2. 初探async await 实现多线程处理

    初探async await 实现多线程处理 这是微软关于Async的介绍:http://msdn.microsoft.com/en-us/library/hh156513.aspx 这是await : ...

  3. OpenSUSE 13.2使用VPN(PPTP)

    新年开始,有时查询个资料或是下个软件包并不是那么愉快,决定使用付费VPN,他们使用的是用户名及密码的验证方式 在网上找到了一个教程,挺详尽的,如果想按照步骤能使用即可的原则,跟着我一起设置,想了解更多 ...

  4. 我的vi/vim配置文件

    位于/etc/vim/的vimrc " All system-wide defaults are set in $VIMRUNTIME/debian.vim and sourced by & ...

  5. [Dev Blog] KCV插件 —— Provissy Tools 。

    承蒙各位支持! 正式版已推出,请前往http://tieba.baidu.com/p/3398574166 或者前往:http://provissy.com/?p=7 请不要在这里回复,我无法保证回复 ...

  6. 【jar包】JSON之解析利器GSON--【gson-2.2.4.jar】

    Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为串行化Java对象为JSON字符串,或反串行化JSON字符串成Java对象.GSON核心jar包不到 ...

  7. Android--扫描二维码

    http://www.cnblogs.com/keyindex/archive/2011/06/08/2074900.html

  8. SpringMVC全注解

    SpringMVC全注解不是你们那么玩的 前言:忙了段时间,忙得要死要活,累了一段时间,累得死去活来. 偶尔看到很多零注解配置SpringMVC,其实没有根本的零注解. 1)工程图一张: web.xm ...

  9. Julia语言:让高性能科学计算人人可用

    Julia语言:让高性能科学计算人人可用要:一群科学家对现有计算工具感到不满:他们想要一套开源系统,有C的快速,Ruby的动态,Python的通用,R般在统计分析上得心应手,Perl的处理字符串处理, ...

  10. 在线web编辑器

    真正在线编辑的在线web编辑器 最近正在研究开发一款在线web编辑器架构,这是一款真正傻瓜式的web编辑器,可以在正常浏览页面的情况进行编辑,经过测试,对于一般网页页面来说非常好用方便,操作更简单. ...