C++ deque详解以及容器适配器

目录

1.容器适配器

2.deque的使用

2.1deque的介绍

2.2deque的缺陷

 2.3deque作为stack和queue的可行性

2.4 deque类的使用

2.4.1deque的构造函数

2.4.2deque容量操作

2.4.3deque赋值,插入


1.容器适配器

适配器是一种设计模式(设计模式是一套被人反复使用,经过分类编目的,代码设计经验的的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

stack的适配器是deque

queue的适配器和stack一样,也是queue

priority_queue的适配器是vector

根据需要进行的操作的不同,我们会在底层选择不同的适配器,比如stack和queue会进行较多的头删和头插操作,底层使用deque比较方便。

2.deque的使用

2.1deque的介绍

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高

 deque的操作图示:

 

 但是deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

  deque 是由一段一段的定量的连续空间构成。一旦有必要在 deque 前端或者尾端增加新的空间,便配置一段连续定量的空间,串接在 deque 的头端或者尾端。Deque 最大的工作就是维护这些分段连续的内存空间的整体性的假象,并提供随机存取的接口,避开了重新配置空间,复制,释放,代价就是复杂的迭代器架构。

deque 是分段连续内存空间,有中央控制,维持整体连续的假象。中控器中每一个节点都是一个指针,指向真正的缓存区。

 双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:

 对于迭代器:first指向第一个buf的开始last指向第一个buf的结束cur指向buf中的一个数据node指向存储当前buf指针的中控位置

class deque
{
    iterator start;
    iterator finish;
}

start指向第一个buf,cur指向这个buf的第一个数据。

finish指向最后一个buf,cur指向这个buf的最后一个数据的下一个位置。


2.2deque的缺陷

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段

但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。

 2.3deque作为stack和queue的可行性

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。

2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。结合了deque的优点,而完美的避开了其缺陷

2.4 deque类的使用

2.4.1deque的构造函数

构造说明
deque<T> deqT;默认构造形式
deque(beg, end);构造函数将[beg, end)区间中的元素拷贝给本身
deque(n, elem)构造函数将n个elem拷贝给本身。
deque(const deque &deq)拷贝构造函数

2.4.2deque容量操作

操作说明
deque.size()返回容器中元素的个数
deque.empty()判断容器是否为空
deque.resize(num)重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem)

重新指定容器的长度为num,若容器变长,则以elem值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。

2.4.3deque赋值,插入

操作说明
assign(beg, end)将[beg, end)区间中的数据拷贝赋值给本身
assign(n, elem)将n个elem拷贝赋值给本身
deque& operator=(const deque &deq)重载等号操作符
swap(deq)将deq与本身的元素互换
push_back(elem)在容器尾部添加一个数据
pop_back()删除容器最后一个数据
push_front(elem)在容器头部插入一个数据
pop_front()删除容器第一个数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值