std::deque
2015-09-06 11:36
399 查看
http://classfoo.com/ccby/article/ryIpw
双端队列(Double-ended queue,缩写为Deque)是一个大小可以动态变化(Dynamic size)且可以在两端扩展或收缩的顺序容器。
A deque is a sequence container that, like a vector, supports random access iterators. In addition, it supports constant time insert and erase operations at the beginning or the end; insert and erase in the middle
take linear time.
C++编程语言国际标准:ISO/IEC
14882:2011
容性特性:
顺序序列
顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。
动态数组
通常采用动态数组这一数据结构。支持对序列中的任意元素进行快速直接访问。操供了在序列末尾相对快速地添加/删除元素的操作。
能够感知内存分配器的(Allocator-aware)
容器使用一个内存分配器对象来动态地处理它的存储需求。
存储在容器中的元素的数据类型。
在类模板内部,使用其别名为
Alloc
容器内部用来管理内存分配及释放的内存分配器的类型。
这个参数是可选的,它的默认值是
容器实际分配的内存数超过容纳当前所有有效元素所需的,因为额外的内存将被未来增长的部分所使用。就因为这点,当插入元素时,容器不需要太频繁地分配内存。
因此,双端队列提供了类似向量(
A deque is especially optimized for pushing and popping elements at the beginning and end.
C++编程语言国际标准:ISO/IEC
14882:2011
但是,相比向量,双端队列不保证内部的元素是按连续的存储空间存储的,因此,不允许对指针直接做偏移操作来直接访问元素。
在内部,双端队列与向量的工作方式完全不同:向量使用单数组数据结构,在元素增加的过程中,需要偶尔的内存重分配,而双端队列中的元素被零散地保存在不同的存储块中,容器内部会保存一些必要的数据使得可以以恒定时间及一个统一的顺序接口直接访问任意元素。因此,双端队列的内部实现比向量的稍稍复杂一点,但这也使得它在一些特定环境下可以更高效地增长,特别是对于非常长的序列,内存重分配的代价是及其高昂的。
对于大量涉及在除了起始或末尾以外的其它任意位置插入或删除元素的操作,相比列表(
版本0
评论0
我来编辑
版本0
评论0
我来编辑
Iterators:
Capacity:
Element access:
Modifiers:
Allocator:
版本0
评论0
我来编辑
版本1
评论0
我来编辑
<algorithm> 头文件中包含大量与
与算法 主题,该主题包含大量的代码示例。
版本1
评论0
我来编辑
注意!以下代码仅用于快速了解
与算法 主题。
可以这样使用:
std::deque
// <deque> template < class T, class Alloc = allocator<T> > class deque;
双端队列(Double-ended queue,缩写为Deque)是一个大小可以动态变化(Dynamic size)且可以在两端扩展或收缩的顺序容器。
A deque is a sequence container that, like a vector, supports random access iterators. In addition, it supports constant time insert and erase operations at the beginning or the end; insert and erase in the middle
take linear time.
C++编程语言国际标准:ISO/IEC
14882:2011
容性特性:
顺序序列
顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。
动态数组
通常采用动态数组这一数据结构。支持对序列中的任意元素进行快速直接访问。操供了在序列末尾相对快速地添加/删除元素的操作。
能够感知内存分配器的(Allocator-aware)
容器使用一个内存分配器对象来动态地处理它的存储需求。
模板参数
T存储在容器中的元素的数据类型。
在类模板内部,使用其别名为
value_type的成员类型。
Alloc
容器内部用来管理内存分配及释放的内存分配器的类型。
这个参数是可选的,它的默认值是
std::allocator<T>,这个是一个最简单的非值依赖的(Value-independent)内存分配器。在类模板内部,使用其别名为
allocator_type的成员类型。
详细说明
不同的库可能会按不同的方式来实现双端队列,通常实现为某种形式的动态数组。但不管通过哪种方式,双端队列都允许通过随机迭代器直接访问各个元素,且内部的存储空间会按需求自动地扩展或收缩。容器实际分配的内存数超过容纳当前所有有效元素所需的,因为额外的内存将被未来增长的部分所使用。就因为这点,当插入元素时,容器不需要太频繁地分配内存。
因此,双端队列提供了类似向量(
std::vector)的功能,且不仅可以在容器末尾,还可以在容器开头高效地插入或删除元素。
A deque is especially optimized for pushing and popping elements at the beginning and end.
C++编程语言国际标准:ISO/IEC
14882:2011
但是,相比向量,双端队列不保证内部的元素是按连续的存储空间存储的,因此,不允许对指针直接做偏移操作来直接访问元素。
在内部,双端队列与向量的工作方式完全不同:向量使用单数组数据结构,在元素增加的过程中,需要偶尔的内存重分配,而双端队列中的元素被零散地保存在不同的存储块中,容器内部会保存一些必要的数据使得可以以恒定时间及一个统一的顺序接口直接访问任意元素。因此,双端队列的内部实现比向量的稍稍复杂一点,但这也使得它在一些特定环境下可以更高效地增长,特别是对于非常长的序列,内存重分配的代价是及其高昂的。
对于大量涉及在除了起始或末尾以外的其它任意位置插入或删除元素的操作,相比列表(
std::list)及正向列表(
std::forward_list),
deque所表现出的性能是极差的,且操作前后的迭代器、引用的一致性较低。
成员类型
ClassFoo 编辑于 07-28版本0
评论0
我来编辑
成员类型 | 定义 |
---|---|
value_type | 第一个模板参数 T |
allocator_type | 第二个模板参数 Alloc |
size_type | 无符号整数类型(通常为 size_t) |
difference_type | 有符号整数类型(通常为 ptrdiff_t) |
reference | Allocator::reference已弃用 value_type&C++11 |
const_reference | Allocator::const_reference已弃用 const value_type&C++11 |
pointer | Allocator::pointer已弃用 std::allocator_traits<Allocator>::pointerC++11 |
const_pointer | Allocator::const_pointer 已弃用std::allocator_traits<Allocator>::const_pointerC++11 |
iterator | 随机访问迭代器 |
const_iterator | 常量随机访问迭代器 |
reverse_iterator | std::reverse_iterator<iterator> |
const_reverse_iterator | std::reverse_iterator<const_iterator> |
成员函数
ClassFoo 编辑于 07-28版本0
评论0
我来编辑
(constructor) | 创建 deque |
(destructor) | 释放 deque |
operator= | 值赋操作 |
begin | 返回指向容器起始位置的迭代器(iterator) |
end | 返回指向容器末尾位置的迭代器 |
rbegin | 返回指向容器逆序起始位置的逆序迭代器(reverse_iterator) |
rend | 返回指向容器逆序末尾位置的逆序迭代器 |
cbeginC++11 | 返回指向容器起始位置的常迭代器(const_iterator) |
cendC++11 | 返回指向容器末尾位置的常迭代器 |
crbeginC++11 | 返回指向容器逆序起始位置的常逆序迭代器(const_reverse_iterator) |
crendC++11 | 返回指向容器逆序末尾位置的常逆序迭代器 |
size | 返回有效元素个数 |
max_size | 返回 deque支持的最大元素个数 |
resize | 改变有效元素的个数 |
empty | 判断是否为空 |
shrink_to_fitC++11 | 请求移除未使用的存储空间 |
operator[] | 访问元素 |
at | 访问元素 |
front | 访问第一个元素 |
back | 访问最后一个元素 |
assign | 将新的内容赋值给容器 |
push_back | 在末尾增加一个元素 |
push_front | 在开头增加一个元素 |
pop_back | 删除最后一个元素 |
pop_front | 删除第一个元素 |
insert | 插入元素 |
erase | 删除元素 |
swap | 交换内容 |
clear | 清空内容 |
emplaceC++11 | 构造及插入一个元素 |
emplace_frontC++11 | 在容器开头构造及插入一个元素 |
emplace_backC++11 | 在容器末尾构造及插入一个元素 |
get_allocator | 获得内存分配器 |
非成员函数
ClassFoo 编辑于 07-28版本0
评论0
我来编辑
operator==、operator!=、operator<、operator<=、operator>、operator>= | 关系操作符 |
std::swap | 交换两个双端队列的内容 |
算法相关
ClassFoo 编辑于 10-13版本1
评论0
我来编辑
<algorithm> 头文件中包含大量与
deque相关的算法,常使用的有:
std::vector的例子基本上都适用于
std::deque,可以参考 vector
与算法 主题,该主题包含大量的代码示例。
代码示例
ClassFoo 编辑于 10-13版本1
评论0
我来编辑
注意!以下代码仅用于快速了解
deque,具体代码示例请查看各个成员函数或上章节提到的 vector
与算法 主题。
综合
下面这个例子简单地介绍了deque的常用使用方法:
#include <iostream> #include <deque> #include <algorithm> // std::sort namespace ClassFoo{ void PrintIntDeque(std::deque<int>& deq, char* pre) { std::deque<int>::iterator it; std::cout << pre; for ( it = deq.begin(); it != deq.end(); it++ ) std::cout << *it << " "; std::cout << std::endl; } void DequeExample1() { // 创建一个deque std::deque<int> foo; // 在 deque 头插入元素 foo.push_front(6); foo.push_front(16); foo.push_front(1); foo.push_front(23); PrintIntDeque(foo,"在开头插入3个元素:"); // 在 deque 尾插入元素 foo.push_back(10); foo.push_back(30); foo.push_back(20); PrintIntDeque(foo,"在末尾插入3个元素:"); // 排序 std::sort(foo.begin(),foo.end()); PrintIntDeque(foo,"排序:"); // 去掉最小值 foo.pop_front(); PrintIntDeque(foo,"去掉最小值:"); // 去掉最大值 foo.pop_back(); PrintIntDeque(foo,"去掉最大值:"); std::random_shuffle(foo.begin(),foo.end()); PrintIntDeque(foo,"随机打乱:"); std::cout << "逆序输出:"; std::deque<int>::reverse_iterator rit; for (rit = foo.rbegin(); rit != foo.rend(); rit++ ) std::cout << *rit << " "; std::cout << std::endl; } } int main(void) { ClassFoo::DequeExample1(); return 0; }
一个有用的宏
类似 C++11 标准中新增的初始化列表构造函数。#define CLASSFOO_DEQUE(type, name, ...) \ static const type name##_a[] = __VA_ARGS__; \ std::deque<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))
可以这样使用:
CLASSFOO_DEQUE(int,foo,{1,2,3,4,5,6,7});
相关文章推荐
- [性能]StringBuilder与StringBuffer的区别(转)
- UIKit;多任务
- Implement Stack using Queues 两个队列实现一个栈
- 实现当tableview当向上滚动时,头部添加的view看上去不随向上滚动的效果
- [LintCode]Segment Tree Build 构造线段树
- UITextView的动态适应高度处理
- SOAPUI系列14- SOAPUI 数据生成器组件使用方法
- SOAPUI系列12- 使用 SOAPUI 执行负载测试
- SOAPUI系列11- 测试步骤中设置断言
- SOAPUI系列10- SOAPUI 循环设置
- SOAPUI系列09- SOAPUI 属性传递之二
- SOAPUI系列08- SOAPUI 属性设置
- UIControl的使用
- queue
- SOAPUI系列07-SOAPUI 断言之三
- std::queue
- SOAPUI系列06-SOAPUI 断言(XPATH)
- SOAPUI系列05-SOAPUI 断言设置
- SOAPUI系列04-SOAPUI 项目新建
- 初学GtkBuilder界面开发