deque
1、deque概述
vector
是单向开口的连续线性空间,而deque
是双向开口的连续线性空间。
vector
和deque
最大的差异:
deque
允许在常数时间内对头端进行元素的插入和移除操作deque
没有“容量”的概念,因为它是以动态地连续空间组合而成,随时可以增加一段新的空间并链接起来。
2、deque的中控器
deque
采用一块map
作为主控。这里的map
是一小块连续空间,其中每个元素(此处称为一个节点,node)都是指针,指向另一段连续线性空间,称为缓冲区。这个缓冲区deque
才是储存空间主体。SGI STL
允许我们指定缓冲区大小,默认值0表示将使用512bytes缓冲区
template<class T, class Alloc = alloc, size_t BufSiz=0>
class deque{
public:
typedef T value_type;
typedef value_type* pointer;
...
protected:
// 元素的指针的指针
typedef pointer* map_pointer;
protected:
map_pointer map; // 指向map,map是块连续空间,其中的每个元素都是一个指向一块连续线性空间缓冲区的指针
size_type map_size; // map内容纳多少指针
};
3、deque的迭代器
deque
是分段连续空间,维持其"整体连续"的假象的任务。
deque
的迭代器的大致结构如下:
template<class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator{
...
// 保持与容器的联结
T* cur; // 此迭代器所指之缓冲区的现行元素
T* first; // 此迭代器所指之缓冲区的头
T* last; // 此迭代器所指缓冲区的尾部(含备用空间)
map_poinetr node; // 指向管控中心
}
对迭代器进行加、减、前进、后退的各类操作中,最关键的是:一旦行进到缓冲区边缘,要特别当心,视前进或后退而定,可能需要调用set_node()
跳一个缓冲区:
void set_node(map_point new_node)
{
node = new_node;
first = *new_node;
last = first + difference_type(buffer_size());
}
4、deque的数据结构
deque
除了维护先前说过的指向map
的指针外,也维护start
、finish
两个迭代器,分别指向第一缓冲区的第一个元素和最后缓冲区的最后一个元素的下一个位置。- 此外,也必须记住目前的
map
大小。因为一旦map
所提供的节点不足,就必须重新配置更大的一块map
template<class T, class Alloc=alloc, size_t BufSiz = 0>
class deque{
public:
typedef T value_type;
typedef value_type* pointer;
typedef size_t size_type;
public:
typedef __deque_iterator<T, T&, T*, BufSiz> iterator; // 迭代器
protected:
// 元素的指针的指针
typedef poinetr* map_pointer;
protected:
iterator start; // deque的第一个节点
iterator finish; // 最后一个节点
map_pointer map; // 指向map,其中每个元素是指向连续线性空间的地址
size_type map_size; // map可以容纳多少个指针
......
}
有了以上结构,以下机能便可请以完成:
iterator begin() { return start; }
iterator end() { return finish; }
...
5、deque的元素操作
构造与赋值
deque(); // 默认构造
explicit deque(size_type count, const T& value = T(), const Allocator& alloc = Allocator());
template <class InputIt>
deque(InputIt first, InputIt last, const Allocator& alloc = Allocator());
deque(const deque& other); // 拷贝构造
deque(deque&& other) noexcept; // 移动构造
~deque(); // 析构
deque& operator=(const deque& other); // 拷贝赋值
deque& operator=(deque&& other) noexcept; // 移动赋值
void assign(size_type count, const T& value); // 赋值
template <class InputIt>
void assign(InputIt first, InputIt last); // 范围赋值
元素访问
// 访问指定位置元素
T& at(size_type pos);
// 下标访问
T& operator[](size_type pos);
// 常量访问
const T& at(size_type pos) const;
// 常量下标访问
const T& operator[](size_type pos) const;
T& front(); // 获取队头元素
T& back(); // 获取队尾元素
const T& front() const; // 常量获取队头元素
const T& back() const; // 常量获取队尾元素
修改容器
void push_back(const T& value); // 在队尾添加元素
void push_front(const T& value); // 在队头添加元素
void pop_back(); // 删除队尾元素
void pop_front(); // 删除队头元素
void insert(const_iterator pos, const T& value); // 插入元素
void erase(const_iterator pos); // 删除指定位置元素
void clear(); // 清空容器
void resize(size_type count, const T& value = T()); // 调整大小
容量
size_type size() const; // 获取元素数量
size_type max_size() const; // 最大容量
bool empty() const; // 检查是否为空