您的位置:首页 > 产品设计 > UI/UE

std::deque

2015-09-06 11:36 399 查看
http://classfoo.com/ccby/article/ryIpw

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>::pointer
C++11
const_pointer
Allocator::const_pointer 已弃用

std::allocator_traits<Allocator>::const_pointer
C++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=
值赋操作
​Iterators:
begin
返回指向容器起始位置的迭代器(
iterator
end
返回指向容器末尾位置的迭代器
rbegin
返回指向容器逆序起始位置的逆序迭代器(
reverse_iterator
rend
返回指向容器逆序末尾位置的逆序迭代器
cbegin
C++11
返回指向容器起始位置的常迭代器(
const_iterator
cend
C++11
返回指向容器末尾位置的常迭代器
crbegin
C++11
返回指向容器逆序起始位置的常逆序迭代器(
const_reverse_iterator
crend
C++11
返回指向容器逆序末尾位置的常逆序迭代器
Capacity:
size
返回有效元素个数
max_size
返回
deque
支持的最大元素个数
resize
改变有效元素的个数
empty
判断是否为空
shrink_to_fit
C++11
请求移除未使用的存储空间
Element access:
operator[]
访问元素
at
访问元素
front
访问第一个元素
back
访问最后一个元素
Modifiers:
assign
将新的内容赋值给容器
push_back
在末尾增加一个元素
push_front
在开头增加一个元素
pop_back
删除最后一个元素
pop_front
删除第一个元素
insert
插入元素
erase
删除元素
swap
交换内容
clear
清空内容
emplace
C++11
构造及插入一个元素
emplace_front
C++11
在容器开头构造及插入一个元素
emplace_back
C++11
在容器末尾构造及插入一个元素
Allocator:
get_allocator
获得内存分配器

非成员函数

ClassFoo 编辑于 07-28

版本0

评论0

我来编辑

operator==、operator!=、operator<、operator<=、operator>、operator>=
关系操作符
std::swap
交换两个双端队列的内容

算法相关

ClassFoo 编辑于 10-13

版本1

评论0

我来编辑

<algorithm> 头文件中包含大量与
deque
相关的算法,常使用的有:
搜索算法
std::adjacent_find
std::count


std::count_if
std::find


std::find_if
std::find_end


std::find_first_of
std::search


std::search_n
std::equal


std::mismatch
分类排序
std::sort
std::partial_sort


std::stable_sort
二分查找(Binary search)
std::lower_bound
std::upper_bound


std::equal_range
std::binary_search
集合(Set)操作
std::includes
std::set_difference


std::set_intersection
std::set_union


std::set_symmetric_difference
堆(Heap)操作
std::make_heap
std::push_heap


std::pop_heap
std::sort_heap
最大与最小
std::min_element
std::max_element
字典序比较
std::lexicographical_compare
排列生成器
std::next_permutation


std::prev_permutation
第n个元素
std::nth_element
其它操作
std::all_of
std::any_of
std::none_of


std::for_each
std::copy
std::copy_if


std::copy_n
std::copy_backward


std::move
std::move_backward


std::swap_ranges
std::iter_swap


std::transform
std::replace


std::replace_if
std::replace_copy


std::replace_copy_if
std::fill


std::fill_n
std::generate


std::generate_n
std::remove


std::remove_if
std::unique


std::unique_copy
std::reverse


​std::reverse_copy
std::rotate


std::rotate_copy
std::random_shuffle


std::shuffle
std::partition


std::is_partitioned
std::stable_partition


std::partition_copy
std::merge
具体内容详见各个功能函数,适用于
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});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: