C++双端队列

系列文章目录

C++入门

C++类和对象(上)

C++类和对象(中)

C++类和对象(下)

C/C++内存管理

C++string类

C++vector类

C++list类

C++stack和queue



前言

在介绍双端队列以前先来介绍一下容器适配器

适配器是标准库中的一个通用概念,容器,迭代器,和函数都有适配器。本质上,适配器是一种机制,能使某种事物的行为看起来像是另外一种事物一样。一个容器适配器接受一种已有的容器类型,使其行为看起来像是一种不同的类型。stack、queue和priority_queue都是顺序容器适配器,而其在标准库中的底层默认容器就是dequeue。

另外,每个容器适配器都基于底层容器类型的操作定义了自己的特殊操作。我们只可以使用适配器操作,而不能使用底层容器类型的操作。


一、dequeue是什么?

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

在这里插入图片描述

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

在这里插入图片描述

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:

在这里插入图片描述
map是中控器,是一个二级指针,可以通过其访问到每一个缓冲区。同时每一个缓冲区的大小是固定的,可以通过迭代器确定范围。如下:
在这里插入图片描述

二、dequeue的优势

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

所以stack和queue的底层容器都选用了dequeue。

三、dequeue的缺陷

deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。


以下是用C++实现双端队列的代码和详细步骤: ```cpp #include <iostream> using namespace std; #define MAXSIZE 100 // 定义双端队列的最大长度 class Deque { private: int data[MAXSIZE]; // 双端队列的数据存储数组 int left; // 左指针 int right; // 右指针 public: Deque() { // 构造函数,初始化左右指针 left = 0; right = 0; } bool isEmpty() { // 判断队列是否为空 return left == right; } bool isFull() { // 判断队列是否已满 return (right + 1) % MAXSIZE == left; } void push_front(int x) { // 在队头插入元素 if (isFull()) { cout << "Deque is full!" << endl; return; } left = (left - 1 + MAXSIZE) % MAXSIZE; data[left] = x; } void push_back(int x) { // 在队尾插入元素 if (isFull()) { cout << "Deque is full!" << endl; return; } data[right] = x; right = (right + 1) % MAXSIZE; } void pop_front() { // 在队头删除元素 if (isEmpty()) { cout << "Deque is empty!" << endl; return; } left = (left + 1) % MAXSIZE; } void pop_back() { // 在队尾删除元素 if (isEmpty()) { cout << "Deque is empty!" << endl; return; } right = (right - 1 + MAXSIZE) % MAXSIZE; } int front() { // 返回队头元素 if (isEmpty()) { cout << "Deque is empty!" << endl; return -1; } return data[left]; } int back() { // 返回队尾元素 if (isEmpty()) { cout << "Deque is empty!" << endl; return -1; } return data[(right - 1 + MAXSIZE) % MAXSIZE]; } }; int main() { Deque dq; dq.push_front(1); dq.push_back(2); dq.push_front(3); dq.push_back(4); cout << dq.front() << endl; // 输出:3 cout << dq.back() << endl; // 输出:4 dq.pop_front(); dq.pop_back(); cout << dq.front() << endl; // 输出:1 cout << dq.back() << endl; // 输出:2 return 0; } ``` 步骤: 1. 定义一个常量MAXSIZE,表示双端队列的最大长度。 2. 定义一个类Deque,包含数据存储数组data和左右指针left、right。 3. 构造函数初始化左右指针。 4. 定义isEmpty()和isFull()函数,分别判断队列是否为空和已满。 5. 定义push_front()和push_back()函数,在队头和队尾插入元素。 6. 定义pop_front()和pop_back()函数,在队头和队尾删除元素。 7. 定义front()和back()函数,分别返回队头和队尾元素。 8. 在main函数中创建Deque对象dq,测试双端队列的各种操作。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值