deque简单使用
在C++中,双端队列(Double-Ended Queue, deque)是一种具有动态大小的序列容器,允许在两端快速插入和删除元素。与std::vector
相比,std::deque
提供了更加灵活的数据结构,特别是在需要频繁在序列的前端进行插入或删除操作时。
双端队列在<deque>
头文件中定义,是标准模板库(STL)的一部分。
基本操作
插入和删除:
在前端插入(push_front
)和删除(pop_front
)元素。
在尾端插入(push_back
)和删除(pop_back
)元素。
访问元素:
访问首元素(front
)和尾元素(back
)。
随机访问(通过索引访问,如deque[index]
)。
容量:
检查双端队列是否为空(empty
)。
获取双端队列中元素的数量(size
)。
改变双端队列的大小(resize
)。
迭代:
提供迭代器来遍历双端队列中的元素(正向迭代器和反向迭代器)。
#include <iostream>
#include <deque>
int main() {
std::deque<int> myDeque;
// 在尾部插入元素
myDeque.push_back(10);
myDeque.push_back(20);
// 在头部插入元素
myDeque.push_front(5);
myDeque.push_front(2);
std::cout << "Deque elements: ";
for(int elem : myDeque) {
std::cout << elem << " ";
}
std::cout << "\n";
// 访问第一个和最后一个元素
std::cout << "First element: " << myDeque.front() << "\n";
std::cout << "Last element: " << myDeque.back() << "\n";
// 删除头部和尾部元素
myDeque.pop_front();
myDeque.pop_back();
std::cout << "Deque size after pop operations: " << myDeque.size() << "\n";
return 0;
}
deque底层实现探究(部分代码)
__deque_buf_size
函数(deque中单个缓冲区(buffer)可以容纳的元素数量)
inline size_t __deque_buf_size(size_t n, size_t sz) {
return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
}
这个函数用于计算deque中单个缓冲区(buffer)可以容纳的元素数量。接受两个参数,n
表示用户指定的元素数量,sz
表示单个元素的大小。如果n
不为0,就直接使用用户指定的数量。如果n
为0,则根据元素的大小计算。如果单个元素大小小于512字节,那么一个缓冲区将分配足够的空间来存放至少512字节的元素(即512 / sz
个元素),否则只存放一个元素。
__deque_iterator
迭代器
template <class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {//deque迭代器
typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
static size_t buffer_size() {
return __deque_buf_size(BufSiz, sizeof(T)); //结点的大小
}
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T** map_pointer;//结点指针
typedef __deque_iterator self;
T* cur;
T* first;
T* last;
map_pointer node;//结点指针node
__deque_iterator(T* x, map_pointer y)
: cur(x), first(*y), last(*y + buffer_size()), node(y) {}
__deque_iterator() : cur(0), first(0), last(0), node(0) {}
__deque_iterator(const iterator& x)
: cur(x.cur), first(x.first), last(x.last), node(x.node) {}
reference operator*() const {
return *cur;
}
pointer operator->() const {
return &(operator*());
}
difference_type operator-(const self& x) const {
return difference_type(buffer_size()) * (node - x.node - 1) +
(cur - first) + (x.last - x.cur);
}
self& operator++() {
++cur;
if (cur == last) {
set_node(node + 1);
cur = first;
}
return *this;
}
self operator++(int) {
self tmp = *this;
++*this;
return tmp;
}
self& operator--() {
if (cur == first) {
set_node(node - 1);
cur = last;
}
--cur;
return *this;
}
self operator--(int) {
self tmp = *this;
--*this;
return tmp;
}
self& operator+=(difference_type n) {
difference_type offset = n + (cur - first);
if (offset >= 0 && offset < difference_type(buffer_size()))
cur += n;
else {
difference_type node_offset =
offset > 0 ? offset / difference_type(buffer_size())
: -difference_type((-offset - 1) / buffer_size()) - 1;
set_node(node + node_offset);
cur = first + (offset - node_offset * difference_type(buffer_size()));
}
return *this;
}
self operator+(difference_type n) const {
self tmp = *this;
return tmp += n;
}
self& operator-=(difference_type n) {
return *this += -n;
}
self operator-(difference_type n) const {
self tmp = *this;
return tmp -= n;
}
reference operator[](difference_type n) const {
return *(*this + n);
}
bool operator==(const self& x) const {
return cur == x.cur;
}
bool operator!=(const self& x) const {
return !(*this == x);
}
bool operator<(const self& x) const {
return (node == x.node)