一、基本概念
Deque(Double-ended queue)容器,是一种具有队列和栈特性的数据结构。它可以在两端进行插入和删除操作,因此可以看作是一个两端开口的队列或者栈。deque 的结构通常由一个环形数组或双向链表实现。在环形数组实现的 deque 中,插入和删除操作可以通过修改数组的头尾指针来实现。在双向链表实现的 deque 中,每个节点都有前驱和后继指针,插入和删除操作可以通过修改节点的指针来实现。由于 deque 支持双向插入和删除操作,因此它在一些需要频繁插入和删除元素的场景中比普通的队列和栈更加高效。
注意:Deque容器中的元素储存,并不能保证所有的元素都储存到连续的空间内。
Deque被设计为一系列连续的内存块,每个块都包含多个元素。因此,deque中的元素不一定是相邻存储的,而是可以在不同的内存块中。中控器的作用就是维护这些内存块之间的链接关系,以便可以在O(1)时间内访问deque中的任何元素。
中控器是一个数据结构,通常是一个指针数组,用于跟踪deque中的所有块(block)。具体来说,中控器中一般包含一下内容:
- 指向第一个内存块的指针和指向最后一个内存块的指针。
- 每个内存块的起始位置和结束位置。
- 每个内存块中元素的个数。
(这里可以稍微参考一下邻接表,有些相似之处)
中控器还负责动态分配和释放内存块,以确保deque的存储空间始终是有效的,并且可以随着需要而增加或减少。当需要添加或删除元素时,deque可以通过重新分配内存块来保持其性能表现。
Deque与Vector的区别
- 内存分配:vector 在内存中是连续存储的,而 deque 则不是。deque 通常是通过分配多个块来存储元素的,每个块通常包含多个元素。因此,deque 可以更好地处理插入和删除操作,因为它不需要移动元素,但是访问元素时可能会产生额外的开销。
- 迭代器的稳定性:对于 vector,插入或删除元素可能会使迭代器失效,需要重新调整。而 deque 保证插入和删除操作不会影响迭代器的稳定性。
- 访问元素:vector 支持通过下标访问元素,而 deque 也支持下标访问,但访问元素的效率可能低于 vector,因为 deque 中的元素不是连续存储的。
- 尾部插入和删除:在尾部插入和删除元素时,vector 比 deque 更高效。
二者也有很多的相似之处,因此Deque的操作方法可以参考Vector。
二、构造函数
Deque 容器以模板类 deque<T>(T 为存储元素的类型)的形式在 <deque>
头文件中,并位于 std 命名空间中。
方法:
deque<int> d; 创建一个没有任何元素的空 deque 容器
deque<int> d(N) 创建一个具有 N 个元素的 deque 容器,其中每个元素都采用对应类型的默认值
deque<int> d(N, m) 创建一个具有 N 个元素的 deque 容器,并为每个元素都指定初始值m
deque(beg,end) 构造函数将[beg,end)区间中的元素拷贝给本身
deque(const deque &deq) 拷贝构造函数
void Deque()
{
std::deque<int> D1;
for (int i = 0; i < 10; i++)
{
D1.push_back(i);
}
PrintDeque(D1);
std::deque<int> D2(D1.begin(), D1.end());
PrintDeque(D2);
std::deque<int> D3(10, 100);
PrintDeque(D3);
std::deque<int> D4(D3);
PrintDeque(D4);
}
三、 赋值
Deque的赋值方式和Vector基本相同
(1)operator= 赋值
std::deque<int> D2;
D2 = D1;
(2)assign(beg,end)
std::deque<int> D3;
D3.assign(D1.begin(), D1.end());
(3)assign(n,elem)
std::deque<int> D4;
D4.assign(10, 100);
(第一行为初始化)
四、大小操作
和Vector基本一样,不同的是,Deque的操作中没有容量的概念,因为Deque的结构中没有容量的限制,可以无限制的开辟新的连续空间,然后在中控器中添加新的地址以维护空间。
方法:
empty() 判断容器是否为空
size() 返回容器中元素的个数
resize(int num) 重新指定容器的长度为num,若容器边长,则以默认值填充新位置;若容器变短,则末尾超出容器长度的元素被删除。
resize(int num,elem) 重新指定容器的长度为num,若容器边长,则以elem值填充新位置;若容器变短,则末尾超出容器长度的元素被删除。
(示例参考Vector)
五、插入和删除
对于两端的操作
-
push_back() 在容器尾部插入数据
-
pop_back() 删除容器最后一个数据
-
push_fornt() 在容器开头插入一个数据
-
pop_front() 从容器开头移除第一个数据
对于指定位置的操作 插入和删除提供的位置是迭代器
-
insert( pos,elem) 迭代器指向位置pos插入元素elem的拷贝,返回新数据的位置
-
insert( pos,int count,elem) 迭代器指向位置pos插入count个元素elem,无返回值
-
insert(pos,beg,end) 在pos位置插入[beg,end)区间的数据,无返回值
-
erase(pos) 删除pos位置的数据,返回下一个数据的位置
-
erase(beg,end) 删除迭代器指从beg到end之间的元素,返回下一个数据的位置
-
clear()删除容器中所有元素
(与Vector基本相同,示例参考Vector)
六、数据的存取
与Vector操作一样,迭代器可以随机访问
-
at(int idx) 返回索引
idx
所指的数据 -
operator[] 返回索引
idx
所指的数据 -
front() 返回容器第一个数据元素
-
back() 返回容器最后一个数据元素
七、排序
方法:
注意包含头文件<algorithm>
sort( iterator beg,itreator end) //默认为升序
std::deque<int> D1;
D1.push_back(10);
D1.push_back(20);
D1.push_back(30);
D1.push_front(100);
D1.push_front(200);
D1.push_front(300);
PrintDeque(D1); // 300 200 100 10 20 30
std::sort(D1.begin(), D1.end());
PrintDeque(D1);
//降序:std::sort(D1.begin(),D1.end(),[](int &a,int &b){return a>b;})
//也可以采用仿函数
结果为:
就记这么多了。。。