队列是一种操作受限的线性表,对于它的所有插入都在表的一端进行,所有的删除(以至几乎所有的存取)都在表的另一端进行,且这些操作又都是按照先进先出(FIFO)的原则进行的。进行删除的一端称为队头(front),进行插入的一端称为队尾(rear)。没有元素的队列称为空队列(简称空队)。
队列就像生活中排队购物,新来的人只能加入队尾(假设不允许插队),购物结束后先离开的总是队头(假设无人中途离队)。也就是说,先加入队列的成员总是先离开队列,因此队列被称为先进先出(First In First Out)的线性表,简称为FIFO表。如图,在空队列中依次加入元素a1,a2,a3,a4,a5,出队次序仍然是a1,a2,a3,a4,a5 .
队列是受限的线性表,其基本操作包括
IsEmpty()
: 判断队列是否为空;isFull()
:判断队列是否为满;enqueue()
:向队尾添加元素(入队);dequeue()
:删除队首元素(出队);peek()
:获取队首的元素值(存取);同普通线性表一样,队列也可以用顺序存储和链接存储两种方式来实现:
参考前文:【数据结构】线性表(八)队列:顺序队列及其基本操作(初始化、判空、判满、入队、出队、存取队首元素)
参考前文:【数据结构】线性表(九)队列:链式队列及其基本操作(初始化、判空、入队、出队、存取队首元素)
双端队列(Double-ended Queue,简称Deque)可以在队列的头部和尾部进行元素的插入和删除操作,因此可以看作是一种特殊的队列和栈的结合。
双端队列的操作包括:
双端队列可以用于解决一些特定的问题,例如实现滑动窗口最大值、字符串处理等。它的灵活性使得在某些场景下比普通队列更加方便和高效。
#include
#include
stdio.h
用于输入输出操作stdlib.h
用于内存分配和释放typedef struct {
int* elements; // 存储队列元素的数组
int front; // 队列头部索引
int rear; // 队列尾部索引
int size; // 队列的最大容量
} Deque;
void initDeque(Deque* deque, int capacity) {
deque->elements = (int*)malloc(capacity * sizeof(int));
deque->front = -1;
deque->rear = -1;
deque->size = capacity;
}
malloc
分配了一个大小为 capacity * sizeof(int)
的整型数组,并将其地址赋值给 deque->elements
。deque->front
和 deque->rear
初始化为 -1,表示队列为空。deque->size
设置为传入的容量值。int isEmpty(Deque* deque) {
return deque->front == -1;
}
通过检查队列的头部索引是否为-1来判断队列是否为空。
int isFull(Deque* deque) {
return deque->rear == deque->size - 1;
}
通过检查队列的尾部索引是否等于队列的最大容量减1来判断队列是否已满。
void insertFront(Deque* deque, int element) {
if (isEmpty(deque)) {
deque->front = 0;
deque->rear = 0;
} else if (deque->front == 0) {
deque->front = deque->size - 1;
} else {
deque->front--;
}
deque->elements[deque->front] = element;
}
isEmpty(deque)
返回真),则将队列头部和尾部索引都设置为 0。element
存储到队列头部索引对应的位置。void insertRear(Deque* deque, int element) {
if (isEmpty(deque)) {
deque->front = 0;
deque->rear = 0;
} else if (deque->rear == deque->size - 1) {
deque->rear = 0;
} else {
deque->rear++;
}
deque->elements[deque->rear] = element;
}
isEmpty(deque)
返回真),则将队列头部和尾部索引都设置为 0。element
存储到队列尾部索引对应的位置。void deleteFront(Deque* deque) {
if (isEmpty(deque)) {
return;
}
if (deque->front == deque->rear) {
deque->front = -1;
deque->rear = -1;
} else if (deque->front == deque->size - 1) {
deque->front = 0;
} else {
deque->front++;
}
}
isEmpty(deque)
返回真),则直接返回,不进行任何操作。void deleteRear(Deque* deque) {
if (isEmpty(deque)) {
return;
}
if (deque->front == deque->rear) {
deque->front = -1;
deque->rear = -1;
} else if (deque->rear == 0) {
deque->rear = deque->size - 1;
} else {
deque->rear--;
}
}
isEmpty(deque)
返回真),则直接返回,不进行任何操作。int getFront(Deque* deque) {
if (isEmpty(deque)) {
return -1; // 队列为空时返回一个特定的值,可以根据实际情况进行修改
}
return deque->elements[deque->front];
}
isEmpty(deque)
返回真),则返回一个特定的值(这里是 -1),表示队列为空。int getRear(Deque* deque) {
if (isEmpty(deque)) {
return -1; // 队列为空时返回一个特定的值,可以根据实际情况进行修改
}
return deque->elements[deque->rear];
}
isEmpty(deque)
返回真),则返回一个特定的值(这里是 -1),表示队列为空。void freeDeque(Deque* deque) {
free(deque->elements);
}
使用 free
函数释放 deque->elements
指向的动态内存。
int main() {
Deque deque;
int capacity = 5; // 设置队列的容量
// 初始化双端队列
initDeque(&deque, capacity);
// 在队列头部插入元素
insertFront(&deque, 1);
insertFront(&deque, 2);
// 在队列尾部插入元素
insertRear(&deque, 3);
insertRear(&deque, 4);
// 获取队列头部和尾部的元素
printf("Front: %d\n", getFront(&deque));
printf("Rear: %d\n", getRear(&deque));
// 在队列头部删除元素
deleteFront(&deque);
// 在队列尾部删除元素
deleteRear(&deque);
// 获取更新后的队列头部和尾部的元素
printf("Front: %d\n", getFront(&deque));
printf("Rear: %d\n", getRear(&deque));
// 释放队列内存
freeDeque(&deque);
return 0;
}
#include
#include
typedef struct {
int* elements; // 存储队列元素的数组
int front; // 队列头部索引
int rear; // 队列尾部索引
int size; // 队列的最大容量
} Deque;
void initDeque(Deque* deque, int capacity) {
deque->elements = (int*)malloc(capacity * sizeof(int));
deque->front = -1;
deque->rear = -1;
deque->size = capacity;
}
int isEmpty(Deque* deque) {
return deque->front == -1;
}
int isFull(Deque* deque) {
return deque->rear == deque->size - 1;
}
void insertFront(Deque* deque, int element) {
if (isEmpty(deque)) {
deque->front = 0;
deque->rear = 0;
} else if (deque->front == 0) {
deque->front = deque->size - 1;
} else {
deque->front--;
}
deque->elements[deque->front] = element;
}
void insertRear(Deque* deque, int element) {
if (isEmpty(deque)) {
deque->front = 0;
deque->rear = 0;
} else if (deque->rear == deque->size - 1) {
deque->rear = 0;
} else {
deque->rear++;
}
deque->elements[deque->rear] = element;
}
void deleteFront(Deque* deque) {
if (isEmpty(deque)) {
return;
}
if (deque->front == deque->rear) {
deque->front = -1;
deque->rear = -1;
} else if (deque->front == deque->size - 1) {
deque->front = 0;
} else {
deque->front++;
}
}
void deleteRear(Deque* deque) {
if (isEmpty(deque)) {
return;
}
if (deque->front == deque->rear) {
deque->front = -1;
deque->rear = -1;
} else if (deque->rear == 0) {
deque->rear = deque->size - 1;
} else {
deque->rear--;
}
}
int getFront(Deque* deque) {
if (isEmpty(deque)) {
return -1; // 队列为空时返回一个特定的值,可以根据实际情况进行修改
}
return deque->elements[deque->front];
}
int getRear(Deque* deque) {
if (isEmpty(deque)) {
return -1; // 队列为空时返回一个特定的值,可以根据实际情况进行修改
}
return deque->elements[deque->rear];
}
void freeDeque(Deque* deque) {
free(deque->elements);
}
int main() {
Deque deque;
int capacity = 5; // 设置队列的容量
// 初始化双端队列
initDeque(&deque, capacity);
// 在队列头部插入元素
insertFront(&deque, 1);
insertFront(&deque, 2);
// 在队列尾部插入元素
insertRear(&deque, 3);
insertRear(&deque, 4);
// 获取队列头部和尾部的元素
printf("Front: %d\n", getFront(&deque));
printf("Rear: %d\n", getRear(&deque));
// 在队列头部删除元素
deleteFront(&deque);
// 在队列尾部删除元素
deleteRear(&deque);
// 获取更新后的队列头部和尾部的元素
printf("Front: %d\n", getFront(&deque));
printf("Rear: %d\n", getRear(&deque));
// 释放队列内存
freeDeque(&deque);
return 0;
}