目录
1. 什么是双端队列?
双端队列(Deque),全称为Double-Ended Queue,是一种允许从队列的两端进行插入和删除操作的数据结构。它综合了队列和栈的优点,因此可以同时支持队列和栈的操作。在双端队列中,我们可以在队列的前端(头部)和后端(尾部)添加或移除元素。
总之一句话,普通队列是队头出元素,队尾进元素,双端队列是队头队尾均可进出元素。
2. 双端队列数据结构的定义
为了进出元素,实际上就是对元素进行插入删除操作,所以用链式存储。
由于需要在队尾进行删除操作(出队),那么就需要一个prev_rear指针来记录尾结点的前一个结点的指针。
为了帮助理解,给出一个例图,如下:
2.1 结点定义
typedef struct Node {
int data; //存储数据
struct Node* next; //指向下一个结点的指针
} Node;
2.2 双端队列定义(带头结点)
typedef struct Deque {
Node* front; //指向头结点
Node* rear; //指向尾结点
Node* prev_rear; // 指向 rear 的前一个节点
} Deque;
3. 双端队列的基本操作
3.1 初始化
// 初始化双端队列
void initDeque(Deque &deque) {
Node* p = (Node*)malloc(sizeof(Node)); //头结点
p->next = NULL;
deque.front = p; //初始时指向头结点
deque.rear = p; //初始时指向头结点
deque.prev_rear = NULL; //初始时为空
}
3.2 判空
// 判断双端队列是否为空
bool isEmpty(Deque deque) {
return deque.front == deque.rear;
}
3.3 队头插入元素
// 在队头插入元素
void pushFront(Deque &deque, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = deque.front->next;
deque.front->next = newNode;
if (isEmpty(deque)) { //队列原本是空的
deque.rear = newNode;
deque.prev_rear = deque.front;//尾结点的前一个结点是头结点
}
}
3.4 队尾插入元素
// 在队尾插入元素
void pushRear(Deque &deque, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = deque.rear->next;
deque.rear->next = newNode;
deque.prev_rear = deque.rear; //更新尾结点的前一个结点
deque.rear = newNode; //更新尾结点
}
3.5 队头删除元素
// 在队头删除元素
void popFront(Deque &deque) {
if (isEmpty(deque)) { //队空
cout << "队空,无法删除" << endl;
return;
}
//非空
Node* p = deque.front->next; //指向第一个元素的指针
deque.front->next = p->next;
if (p == deque.rear) { //队列只有一个元素
deque.rear = deque.front;
}
free(p);
}
3.6 队尾删除元素
// 在队尾删除元素
void popRear(Deque& deque) {
if (isEmpty(deque)) { //队空
cout << "队空,无法删除" << endl;
return;
}
//非空
Node* p = deque.rear; //指向末尾元素的指针
deque.prev_rear->next = deque.rear->next;
deque.rear = deque.prev_rear;
free(p);
}
3.7 获取队头元素
// 获取队头元素
int getFront(Deque &deque) {
if (!isEmpty(deque)) {//非空
return deque.front->next->data;
}
else {
cout << "队列为空" << endl;
}
}
3.8 获取队尾元素
// 获取队尾元素
int getRear(Deque &deque) {
if (!isEmpty(deque)) {//非空
return deque.rear->data;
}
else {
cout << "队列为空" << endl;
}
}