一说到队列,大家多数人和我一样,第一反应是FIFO原则。
那么双端队列就是一个方向(头或者尾)就可以进也可以出,听起来我们的双端队列是一种具有队列和栈的性质的数据结构。是一种线性的数据结构,相比list增加 [] 运算符重载。
大概长这个样子:
实际上,在内存中这不是他的真实模样,比这个要复杂的多。
一、双端队列deque的基本使用:
#include <iostream>
#include <deque>
int main()
{
// Create a deque containing integers
std::deque<int> d = {7, 5, 16, 8};
// Add an integer to the beginning and end of the deque
d.push_front(13);
d.push_back(25);
// Iterate and print values of deque
for(int n : d) {
std::cout << n << '\n';
}
}
二、deque的特点: 本文重点内容
使用的时候,底层默认只开辟两个元素,一维是个数组(vector),这个一位数组中保存着一段缓存区(数组)地址,也就是一个指针;
二维是个缓冲区,实际上是个数组,长度是确定的,但是二维一开始开辟多大呢?
QUEUESIZE = 4096<sizeof(T)? 1 : 4096/sizeof(T)
,如果单个元素的大小超过4K,那么二维数组只开辟1个元素位置,否则开辟4096/sizeof(T)个元素。(VC++6.0这样定义)一开始first和last放到二维数组的中间,原因还是因为它将来要头尾都要进出元素,所以不能放在头,也不能放在尾,不然总是要扩容,事实上这个二维数组还有空闲位置;
提供四个进出对接口,push_back、pop_front、push_back、pop_back,假设我们一致从头添加数据,知道第一个二维数组满时如下图,新增一个二维数组如下图;
第一个二维数组满时:
新增一个二维数组:如果我继续push_front,直到新增的缓冲区(二维数组)都满了,会发生什么,此时没有可以继续申请的二维数组了,那就要增加一位数组的容量了,这里一维数组的容量是以二倍扩容,
cnt*=2,pos = cnt/2-1
,其中pos表示旧的二维数组将从pos这个位置开始挨个重新布置;从尾部添加同理。deque每次增长完一维数组,都会调整二维数组的位置,保证二维数组的地址处于一维数组的中间,保证头尾都预留位置。
deque提供了operator[]运算符重载重载函数,我们看到实际上deque是不连续的,能实现[],归功于deque强大的迭代器。
这张图是从网上找到的,对于初学者不必细究这张图,否则你可能会有点懵。
三、deque常用接口:
Defined in header <deque>
template<
class T,
class Allocator = std::allocator<T>
> class deque;
Member functions
(constructor)
constructs the deque
(public member function)
(destructor)
destructs the deque
(public member function)
operator=
assigns values to the container
(public member function)
assign
assigns values to the container
(public member function)
get_allocator
returns the associated allocator
(public member function)
Element access
at
access specified element with bounds checking
(public member function)
operator[]
access specified element
(public member function)
front
access the first element
(public member function)
back
access the last element
(public member function)
Iterators
begin
cbegin
returns an iterator to the beginning
(public member function)
end
cend
returns an iterator to the end
(public member function)
rbegin
crbegin
returns a reverse iterator to the beginning
(public member function)
rend
crend
returns a reverse iterator to the end
(public member function)
Capacity
empty
checks whether the container is empty
(public member function)
size
returns the number of elements
(public member function)
max_size
returns the maximum possible number of elements
(public member function)
shrink_to_fit
(C++11)
reduces memory usage by freeing unused memory
(public member function)
Modifiers
clear
clears the contents
(public member function)
insert
inserts elements
(public member function)
emplace
(C++11)
constructs element in-place
(public member function)
erase
erases elements
(public member function)
push_back
adds an element to the end
(public member function)
emplace_back
(C++11)
constructs an element in-place at the end
(public member function)
pop_back
removes the last element
(public member function)
push_front
inserts an element to the beginning
(public member function)
emplace_front
(C++11)
constructs an element in-place at the beginning
(public member function)
pop_front
removes the first element
(public member function)
resize
changes the number of elements stored
(public member function)
swap
swaps the contents
(public member function)
Non-member functions
operator==
operator!=
operator<
operator<=
operator>
operator>=
lexicographically compares the values in the deque
(function template)
std::swap(std::deque)
specializes the std::swap algorithm
(function template)
erase(std::deque)
erase_if(std::deque)
(C++20)
Erases all elements satisfying specific criteria
(function template)
deque扩容时,一维数组进行二倍扩容,二维数组是固定长度的。
四、参考链接:
https://en.cppreference.com/w/cpp/container/deque
https://en.cppreference.com/w/cpp/header/deque