代码实现
#include <stdio.h>
#include <stdlib.h>
// 定义双端队列节点结构体
typedef struct Node {
int data; // 数据域
struct Node* next; // 指针域,指向下一个节点
} Node;
// 定义双端队列结构体
typedef struct Deque {
Node* front; // 队头指针
Node* rear; // 队尾指针
} Deque;
// 初始化双端队列
Deque* initializeDeque() {
Deque* deque = (Deque*)malloc(sizeof(Deque));
deque->front = NULL;
deque->rear = NULL;
return deque;
}
// 判断双端队列是否为空
int isEmpty(Deque* deque) {
return (deque->front == NULL);
}
// 在队头插入元素
void insertFront(Deque* deque, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
if (isEmpty(deque)) {
deque->front = newNode;
deque->rear = newNode;
} else {
newNode->next = deque->front;
deque->front = newNode;
}
}
// 在队尾插入元素
void insertRear(Deque* deque, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
if (isEmpty(deque)) {
deque->front = newNode;
deque->rear = newNode;
} else {
deque->rear->next = newNode;
deque->rear = newNode;
}
}
// 从队头删除元素
int deleteFront(Deque* deque) {
if (isEmpty(deque)) {
printf("Deque is empty.\n");
return -1;
}
int value = deque->front->data;
Node* temp = deque->front;
deque->front = deque->front->next;
if (deque->front == NULL) {
deque->rear = NULL;
}
free(temp);
return value;
}
// 从队尾删除元素
int deleteRear(Deque* deque) {
if (isEmpty(deque)) {
printf("Deque is empty.\n");
return -1;
}
int value = deque->rear->data;
Node* temp = deque->rear;
Node* current = deque->front;
while (current->next != deque->rear) {
current = current->next;
}
deque->rear = current;
deque->rear->next = NULL;
free(temp);
return value;
}
// 获取队头元素
int getFront(Deque* deque) {
if (isEmpty(deque)) {
printf("Deque is empty.\n");
return -1;
}
return deque->front->data;
}
// 获取队尾元素
int getRear(Deque* deque) {
if (isEmpty(deque)) {
printf("Deque is empty.\n");
return -1;
}
return deque->rear->data;
}
// 打印双端队列元素
void printDeque(Deque* deque) {
Node* current = deque->front;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
int main() {
Deque* deque = initializeDeque();
insertFront(deque, 1); // 队头插入元素1
insertFront(deque, 2); // 队头插入元素2
insertRear(deque, 3); // 队尾插入元素3
printDeque(deque); // 输出:2 1 3
deleteFront(deque); // 从队头删除元素
printDeque(deque); // 输出:1 3
deleteRear(deque); // 从队尾删除元素
printDeque(deque); // 输出:1
printf("Front element: %d\n", getFront(deque)); // 输出队头元素:1
printf("Rear element: %d\n", getRear(deque)); // 输出队尾元素:1
return 0;
}
理解:队列是指针指向是从队头指向队尾,理解这一点后对双端队列的队头插入和队尾插入就会简单很多
队头插入:新节点的下一个指向原先的队头,再更新队头为新节点
void insertFront(Deque* deque, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
if (isEmpty(deque)) {
deque->front = newNode;
deque->rear = newNode;
} else {
newNode->next = deque->front;
deque->front = newNode;
}
}
队尾插入:队尾指向新节点,然后把新节点更新为队尾
void insertRear(Deque* deque, int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
if (isEmpty(deque)) {
deque->front = newNode;
deque->rear = newNode;
} else {
deque->rear->next = newNode;
deque->rear = newNode;
//这两行代码的目的是确保在队尾插入元素后,队列的 rear 指针正确指向新的队尾节点,
//并且新的队尾节点的 next 指针指向 NULL,表示它是队列的最后一个节点。
//这是维护双端队列的基本操作之一,确保队列的数据结构保持一致。
}
deleteRear
函数的目标是从双端队列中删除队尾元素,并返回被删除的元素的值。以下是这个函数的实现过程:
int deleteRear(Deque* deque) {
if (isEmpty(deque)) {
printf("Deque is empty.\n");
return -1;
}
int value = deque->rear->data;
Node* temp = deque->rear;
Node* current = deque->front;
while (current->next != deque->rear) {
current = current->next;
}
deque->rear = current;
deque->rear->next = NULL;
free(temp);
return value;
}
-
首先,函数会检查队列是否为空,如果为空(即
isEmpty(deque)
返回真),则会打印 "Deque is empty." 的消息,然后返回 -1,表示删除失败。 -
如果队列不为空,函数会执行以下操作:
a. 获取队尾元素的值:
int value = deque->rear->data;
,这一行代码将队尾节点deque->rear
的数据域data
的值存储在value
变量中,以备后续返回。b. 创建一个临时节点
temp
,并将其指向队尾节点:Node* temp = deque->rear;
,这是为了后续释放队尾节点的内存。c. 创建一个指针
current
并将其初始化为队头节点:Node* current = deque->front;
,这是为了遍历队列以找到队尾节点的前一个节点。d. 使用循环找到队尾节点的前一个节点。循环条件
current->next != deque->rear
意味着当current
的下一个节点不是队尾节点时,继续遍历。这是为了找到队尾节点的前一个节点,因为需要更新队尾指针。e. 更新队尾指针:
deque->rear = current;
,这一行代码将deque->rear
指针更新为队尾节点的前一个节点,从而将队尾节点从队列中移除。f. 将队尾节点的
next
指针设置为NULL
,表示它不再是队列的最后一个节点:deque->rear->next = NULL;
。g. 释放队尾节点的内存,防止内存泄漏:
free(temp);
。 -
最后,函数返回被删除的队尾元素的值,即
return value;
。
这样,deleteRear
函数就可以删除队尾元素并正确地更新队尾指针,同时返回被删除元素的值。