双端队列(deque)
deque是double-ended queue首字母缩写。deque是具有动态大小的序列容器,可以在两端(头部或尾部)扩展或收缩。
特定库可以以不同方式实现deque,通常为某种形式的动态数组。但无论如何,它们允许通过随机访问迭代器直接访问各个元素,并根据需要通过扩展和收缩容器来自动处理存储。
因此,它们提供类似于vector的功能,但是在序列的开头也可以有效地插入和删除元素,而不仅仅是在其结尾。但是,与vector不同,deque不能保证将其所有元素存储在连续的存储位置:通过将指针偏移到另一个元素来访问双端队列中的元素会导致未定义的行为。
vector和deque都提供了非常相似的接口,可以用于类似的目的,但内部都以完全不同的方式工作:虽然vector的使用偶尔需要重新分配,但是deque的元素可以分散在不同的存储块,容器在内部保存必要的信息,以便在恒定的时间内通过迭代器直接访问其任何元素。因此,deque在内部比vector稍微复杂一些,但是这允许它们在某些情况下更有效地增长,特别是在非常长的序列中。
对于涉及在开头或结尾以外的位置频繁插入或删除元素的操作,deque表现更差,并且与list和forward_list相比具有更少的迭代器和引用。
容器属性
序列
序列容器中的元素按严格的线性顺序排序。 各个元素按其顺序访问它们的位置。
动态数组
通常实现为动态数组,它允许直接访问序列中的任何元素,并在序列的开头或结尾提供相对快速的元素添加/删除。
分配器
容器使用allocator对象来动态处理其存储需求。
构造函数:
C++11中deque的构造函数有如下:
(1)空容器构造函数(默认构造函数)
explicit deque (const allocator_type& alloc = allocator_type());
构造一个没有元素的空容器。
(2)填充构造函数
explicit deque (size_type n);
deque (size_type n, const value_type& val,const allocator_type& alloc = allocator_type());
构造一个包含n个元素的容器。 每个元素都是val的副本(如果提供)。
(3)范围构造函数
template <class InputIterator>
deque (InputIterator first, InputIterator last,const allocator_type& alloc = allocator_type());
构造一个容器,其中包含与[first,last]范围一样多的元素,每个元素都以相同的顺序从该范围内的相应元素构造。
(4)拷贝构造函数(和使用allocator复制)
deque (const deque& x);
deque (const deque& x, const allocator_type& alloc);
构造一个容器,其中包含x中每个元素的副本,顺序相同。
(5)移动构造函数(和分配器一起移动)
deque (deque&& x);
deque (deque&& x, const allocator_type& alloc);
构造一个获取x元素的容器。如果指定了alloc并且与x的allocator不同,则移动元素。 否则,不构建任何元素(它们的所有权直接转移)。x处于未指定但有效的状态。
(6)初始化列表构造函数
deque (initializer_list<value_type> il,const allocator_type& alloc = allocator_type());
构造一个容器,其中包含il中每个元素的副本,顺序相同。
// constructing deque
#include <iostream>
#include <deque>
int main ()
{
using namespace std;
unsigned int i;
// constructors
deque<int> one; // Constructs an empty deque, with no elements
deque<int> two(5, 10); // Constructs a deque with 5 elements. Each element is 10
deque<int> three(two.begin(), two.end()); // Constructs a deque with as many elements as the range [first,last)
deque<int> four(three); // Constructs a deque with a copy of each of the elements in three
deque<int> five = {1, 2, 3, 4, 5}; // Constructs a deque with a copy of each of the elements in {1, 2, 3, 4, 5}
cout << "The values of five:";
for(auto& x: five)
{
cout << " " << x;
}
cout << endl;
deque<int> six(move(five)); // Constructs a deque that acquires the elements of five.
cout << "The values of five(after move):";
for(auto& x: five)//empty
{
cout << " " << x;
}
cout << endl;
cout << "The values of six:";
for(auto& x: six)
{
cout << " " << x;
}
cout << endl;
return 0;
}
Iterators:
begin
将迭代器返回到开头(公共成员函数)
end
将迭代器返回到end(公共成员函数)
rbegin
返回反向迭代器以反向开始(公共成员函数)
rend
将反向迭代器返回到反向结束(公共成员函数)
cbegin
将const_iterator返回到开头(公共成员函数)C++11
cend
将const_iterator返回到end(公共成员函数)C++11
crbegin
返回const_reverse_iterator以反向开始(公共成员函数)C++11
crend
将const_reverse_iterator返回到反向结束(公共成员函数)C++11
// deque::begin/end
// deque::rbegin/rend
// deque::cbegin/cend
// deque::crbegin/crend
#include <iostream>
#include <deque>
int main ()
{
using namespace std;
deque<int> dq;
for(int i=1; i<=5; i++)
{
dq.push_back(i);
}
cout << "The values of dq(by begin/end):";
for(auto it=dq.begin(); it != dq.end(); ++it)
{
cout << " " << *it;
}
cout << endl;
cout << "The values of dq(by rbegin/rend):";
for(auto it=dq.rbegin(); it != dq.rend(); ++it)
{
cout << " " << *it;
*it += 10;
}
cout << endl;
cout << "The values of dq(by cbegin/cend):";
for(auto it=dq.cbegin(); it != dq.cend(); ++it)
{
cout << " " << *it;
}
cout << endl;
cout << "The values of dq(by crbegin/crend):";
for(auto it=dq.crbegin(); it != dq.crend(); ++it)
{
cout << " " << *it;
}
cout << endl;
return 0;
}
Capacity:
size
返回大小(公共成员函数)
max_size
返回最大大小(公共成员函数)
resize
更改大小(公共成员函数)
empty
测试容器是否为空(公共成员函数)
shrink_to_fit
缩小到适合(公共成员函数)C++11
// deque::size
// deque::max_size
// deque::resize
// deque::shrink_to_fit
// deque::empty
#include <iostream>
#include <deque>
int main ()
{
using namespace std;
deque<int> dq;
cout << "0. size: " << dq.size() << ", max_size: " << dq.max_size() << endl;
for (int i=1; i<=5; i++)
{
dq.push_back(i);
}
cout << "1. size: " << dq.size() << endl;
dq.resize(10);
cout << "2. size: " << dq.size() << endl;
cout << "The values of dq:";
for(deque<int>::const_iterator cit=dq.cbegin(); cit != dq.cend(); ++cit)
{
cout << " " << *cit;
}
cout << endl;
dq.shrink_to_fit(); //c++11
cout << "3. size: " << dq.size() << endl;
while(!dq.empty())
{
cout << "pop_front:" << dq.front() << endl;
dq.pop_front();
}
return 0;
}
Element access:
operator[]
访问元素(公共成员函数)
at
访问元素(公共成员函数)
front
访问第一个元素(公共成员函数)
back
访问最后一个元素(公共成员函数)
// deque::operator[]
// deque::at
// deque::front
// deque::back
#include <iostream>
#include <deque>
int main ()
{
using namespace std;
deque<int> dq1(10);
deque<int>::size_type sz = dq1.size();
unsigned int i = 0 ;
/*operator[]*/
for(i=0; i<sz; ++i)
{
dq1[i] = i + 1;
}
cout << "the values of dq1:";
for(i = 0; i < sz; ++i)
{
cout << " " << dq1[i];
}
cout << endl;
/*at*/
deque<int> dq2(10);
sz = dq2.size();
for(i = 0; i < sz; ++i)
{
dq2.at(i) = (i + 1) * 10;
}
cout << "the values of dq2:";
for(i = 0; i < sz; ++i)
{
cout << " " << dq2.at(i);
}
cout << endl;
/*front*/
for(i = 0; i < sz; ++i)
{
cout << "dq1: i=" << i <<" front: " << dq1.front() << endl;
dq1.pop_front();
}
/*back*/
for(i = 0; i < sz; ++i)
{
cout << "dq2: i=" << i <<" back: " << dq2.back() << endl;
dq2.pop_back();
}
return 0;
}
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
// deque::assign
// deque::push_back/push_front
// deque::push_back/push_front
// deque::insert
// deque::erase
// deque::emplace/emplace_back/emplace_front
// deque::swap
// deque::clear
#include <iostream>
#include <deque>
int main ()
{
using namespace std;
deque<int> one;
deque<int> two;
deque<int> three;
//assign
one.assign(10,100); // 10 elements with a value of 100
two.assign(one.begin()+1, one.end()-1); // the 8 central values of one
int myarray[] = {1, 2, 3, 4, 5};
three.assign(myarray, myarray+5); // assigning from array.
cout << "1. Size of one: " << one.size() << endl;
cout << "1. Size of two: " << two.size() << endl;
cout << "1. Size of three: " << three.size() << endl;
// push_back/push_front
for(unsigned int i = 0; i < 10 ; ++i)
{
one.push_back(i+1);
two.push_front(i+1);
}
cout << "The value of one:";
for(auto& v : one)
{
cout << " " << v;
}
cout << endl;
//pop_front
while(!one.empty())
{
one.pop_front();
}
cout << "The value of two:";
for(auto& v : two)
{
cout << " " << v;
}
cout << endl;
//pop_back
while(!two.empty())
{
two.pop_back();
}
//insert
three.insert(three.begin()+2, 987);
cout << "The value of three:";
for(auto& v : three)
{
cout << " " << v;
}
cout << endl;
//erase
while(!three.empty())
{
three.erase(three.begin());
}
cout << "2. Size of one: " << one.size() << endl;
cout << "2. Size of two: " << two.size() << endl;
cout << "2. Size of three: " << three.size() << endl;
//emplace/emplace_back/emplace_front
for(unsigned int i = 0; i < 10; ++i)
{
one.emplace(one.begin(), i);
two.emplace_back(i);
three.emplace_front(i);
}
cout << "The value of one:";
for(auto& v : one)
{
cout << " " << v;
}
cout << endl;
cout << "The value of two:";
for(auto& v : two)
{
cout << " " << v;
}
cout << endl;
cout << "The value of three:";
for(auto& v : three)
{
cout << " " << v;
}
cout << endl;
//swap
one.swap(two);
//clear
three.clear();
cout << "The value of one:";
for(auto& v : one)
{
cout << " " << v;
}
cout << endl;
cout << "The value of two:";
for(auto& v : two)
{
cout << " " << v;
}
cout << endl;
cout << "The value of three:";
for(auto& v : three)
{
cout << " " << v;
}
cout << endl;
return 0;
}
Allocator:
get_allocator
获取分配器(公共成员函数)
// deque::get_allocator
#include <iostream>
#include <deque>
int main ()
{
using namespace std;
deque<int> dq;
int * p;
unsigned int i;
// allocate
p = dq.get_allocator().allocate(5);
// construct
for (i=0; i<5; i++)
{
dq.get_allocator().construct(&p[i], (i+1)*10);
}
cout << "The allocated array contains:";
for (i=0; i<5; i++)
{
cout << ' ' << p[i];
}
cout << endl;
// destroy
for (i=0; i<5; i++)
{
dq.get_allocator().destroy(&p[i]);
}
// deallocate
dq.get_allocator().deallocate(p, 5);
return 0;
}