队列(Queue)是操作受限的线性表。它限制为仅允许在表的一端进行插入操作(入队或进队),在表的另一端进行删除操作(出队或离队)。队列是具有先进先出(FIFO,First In First Out)特点的线性结构,类似于生活中的排队现象。
组成部分
操作
队列元素顺序
在空队列中依次加入元素 a1,a2,…,an 之后,a1a_1a1 是队首元素,an 是队尾元素。显然,出队列的次序只能是 a1,a2,…,an。
空队列
队列中没有元素时,称为空队列。

从图中可以看出:
队列遵循先入先出原则,即先进入队列的元素先离开队列。
队列的基本操作
在实现队列时,通常有以下基本操作:
队列的存储结构有两种主要实现方式:顺序队列和链式队列。以下是对这两种实现方式的详细解释。
顺序队列使用数组来存储队列元素。由于数组的定长特性,顺序队列在存储和管理队列元素时有一定的限制,但实现相对简单。
特点
操作
链式队列使用链表来存储队列元素。相比于顺序队列,链式队列可以动态调整容量,更适合需要频繁调整队列大小的场景。
特点
操作
顺序队列的优缺点
链式队列的优缺点
队列是一种操作受限的线性表,只允许在表的一端进行插入操作(入队或进队),在表的另一端进行删除操作(出队或离队)。
队列的存储结构
队列可以使用顺序表(数组)或链表来实现,根据存储结构可以分为顺序队列和链式队列两种。
顺序队列使用数组来存储队列元素。队首指针指向队列第一个元素的位置,队尾指针指向队列最后一个元素的下一个位置。

顺序队列中可能会出现“假溢出”现象,即队列中实际元素个数远小于数组大小,但由于 rear 已超过数组容量的上界而不能进行入队操作。
为了解决这个问题,有以下两种方法:
循环队列将数组首尾相连,形成一个环形结构,front 和 rear 指针在环形数组中循环移动。这样可以充分利用数组空间,避免“假溢出”现象。
循环队列的常见操作
在循环队列中,入队操作将元素插入队列的最后,rear 指针向后移动;出队操作将元素从队列的前端移除,front 指针向后移动。
initQueue功能:初始化队列,为队列分配内存,并设置队首、队尾指针和容量。
- void initQueue(Queue *queue, size_t capacity) {
- // 为队列的数据部分分配内存
- queue->data = (int *)malloc(capacity * sizeof(int));
- // 初始化队首指针,指向数组的第一个位置
- queue->front = 0;
- // 初始化队尾指针,指向数组的第一个位置
- queue->rear = 0;
- // 设置队列的容量
- queue->capacity = capacity;
- // 初始化队列的元素个数为0
- queue->size = 0;
- }
malloc 分配容量大小的内存。front 和 rear 初始化为0。capacity 设置为传入的参数值。size 初始化为0。getSize功能:返回队列内元素的个数。
- size_t getSize(const Queue *queue) {
- return queue->size; // 返回当前队列的元素个数
- }
size 值。isEmpty功能:检查队列是否为空。
- bool isEmpty(Queue *queue) {
- return queue->size == 0; // 如果队列的元素个数为0,则队列为空
- }
size 是否为0。isFull功能:检查队列是否已满。
- bool isFull(Queue *queue) {
- return queue->size == queue->capacity; // 如果队列的元素个数等于容量,则队列已满
- }
size 是否等于 capacity。enqueue功能:在队尾插入元素。如果队列已满,打印错误信息。
- void enqueue(Queue *queue, int element) {
- if (isFull(queue)) {
- printf("队列已满,无法入队!\n");
- return;
- }
- // 将新元素添加到队尾位置
- queue->data[queue->rear] = element;
- // 更新队尾指针,指向下一个位置(循环队列)
- queue->rear = (queue->rear + 1) % queue->capacity;
- // 更新队列的元素个数
- queue->size++;
- }
isFull 函数。rear 指针指向的位置。rear:将 rear 更新为 (rear + 1) % capacity 实现循环。size:增加元素个数。dequeue功能:从队首移除元素并返回。如果队列为空,返回-1。
- int dequeue(Queue *queue) {
- if (isEmpty(queue)) {
- printf("队列为空,无法出队!\n");
- return -1;
- }
- // 获取队首元素的值
- int value = queue->data[queue->front];
- // 更新队首指针,指向下一个位置(循环队列)
- queue->front = (queue->front + 1) % queue->capacity;
- // 更新队列的元素个数
- queue->size--;
- // 返回被移除的队首元素
- return value;
- }
isEmpty 函数。front 指针指向的元素值。front:将 front 更新为 (front + 1) % capacity 实现循环。size:减少元素个数。destroyQueue功能:释放队列的内存,重置指针和容量。
- void destroyQueue(Queue *queue) {
- free(queue->data); // 释放动态数组内存
- queue->data = NULL;
- queue->front = 0;
- queue->rear = 0;
- queue->capacity = 0;
- queue->size = 0;
- }
free 释放 data 部分的内存。data 设置为 NULL,将 front、rear、capacity 和 size 都设置为0。printQueue功能:打印队列中的所有元素。
- void printQueue(Queue *queue) {
- if (isEmpty(queue)) {
- printf("队列为空!\n");
- return;
- }
- int i = queue->front;
- for (int count = 0; count < queue->size; count++) {
- printf("%d ", queue->data[i]);
- i = (i + 1) % queue->capacity; // 循环访问队列元素
- }
- printf("\n");
- }
isEmpty 函数。front 开始,循环打印每个元素,使用 (i + 1) % capacity 实现循环访问。以下是一个完整代码,实现了创建并初始化队列,进行入队、出队操作,打印队列内容,最后释放队列内存的基本操作。
- #include <stdio.h>
- #include <stdlib.h>
-
- // 队列结构体定义
- typedef struct
- {
- int *data; // 动态数组存储队列元素
- size_t size; // 队列内元素个数
- size_t capacity; // 动态数组的容量
- size_t front; // 队列头指针
- size_t rear; // 队列尾指针
- } Queue;
-
- // 初始化队列函数
- void initQueue(Queue *queue, size_t capacity)
- {
- queue->data = (int *)malloc(capacity * sizeof(int)); // 分配初始容量的内存
- queue->size = 0; // 初始元素个数为0
- queue->capacity = capacity; // 设置容量
- queue->front = 0; // 初始化队列头指针
- queue->rear = 0; // 初始化队列尾指针
- }
-
- // 返回队列内元素个数函数
- size_t getSize(const Queue *queue)
- {
- return queue->size;
- }
-
- // 入队函数
- void enqueue(Queue *queue, int element)
- {
- // 检查队列是否已满
- if (queue->size == queue->capacity)
- {
- printf("队列已满,添加失败\n");
- return;
- }
- // 将元素添加到队列尾部
- queue->data[queue->rear] = element;
- // 循环更新队列尾指针
- queue->rear = (queue->rear + 1) % queue->capacity;
- // 更新元素个数
- queue->size++;
- }
-
- // 出队函数
- int dequeue(Queue *queue)
- {
- // 检查队列是否为空
- if (queue->size == 0)
- {
- printf("队列为空,无法出队!\n");
- return -1; // 队列为空,返回无效值
- }
- // 获取队列头部元素
- int dequeuedElement = queue->data[queue->front];
- // 循环更新队列头指针
- queue->front = (queue->front + 1) % queue->capacity;
- // 更新元素个数
- queue->size--;
- // 返回出队的元素
- return dequeuedElement;
- }
-
- // 释放队列内存函数
- void destroyQueue(Queue *queue)
- {
- free(queue->data); // 释放动态数组内存
- queue->data = NULL;
- queue->size = 0;
- queue->capacity = 0;
- queue->front = 0;
- queue->rear = 0;
- }
-
- // 遍历队列并打印函数
- void printQueue(Queue *queue)
- {
- // 检查队列是否为空
- if (queue->size == 0)
- {
- printf("队列为空!\n");
- return;
- }
- // 遍历队列元素
- for (int i = queue->front, j = 0; j < queue->size; i++, j++)
- {
- // 打印当前元素
- int data = queue->data[i % queue->capacity];
- printf("%d ", data);
- }
- printf("\n");
- }
-
- int main()
- {
- Queue myQueue;
-
- // 初始化队列
- initQueue(&myQueue, 2);
- printf("初始化队列,初始容量为2\n");
-
- // 入队元素
- enqueue(&myQueue, 1);
- enqueue(&myQueue, 2);
-
- // 打印队列内元素个数
- printf("队列内元素个数:%zu\n", getSize(&myQueue));
-
- // 打印队列内容
- printf("当前队列内容:");
- printQueue(&myQueue);
-
- // 出队元素
- printf("出队元素:%d\n", dequeue(&myQueue));
-
- // 再次打印队列内容
- printf("当前队列内容:");
- printQueue(&myQueue);
-
- // 再次入队元素
- enqueue(&myQueue, 3);
- printf("再次入队元素3\n");
-
- // 打印队列内容
- printf("当前队列内容:");
- printQueue(&myQueue);
-
- // 释放队列内存
- destroyQueue(&myQueue);
- printf("队列内存已释放\n");
-
- return 0;
- }
定义队列结构体:
data:动态数组,用于存储队列元素。size:当前队列中元素的个数。capacity:动态数组的容量。front:队列头指针,指向队列的第一个元素。rear:队列尾指针,指向队列的最后一个元素的下一个位置。初始化队列函数 initQueue:
malloc 为队列的数据部分分配内存。size 为0,capacity 为传入的参数值,front 和 rear 都初始化为0。获取队列大小函数 getSize:
size 值,即当前队列中的元素个数。入队函数 enqueue:
size 等于 capacity,队列已满,打印错误信息。rear 指针指向的位置。rear 指针,并增加 size。出队函数 dequeue:
size 为0,队列为空,打印错误信息并返回-1。front 指针指向的元素值。front 指针,并减少 size。释放队列内存函数 destroyQueue:
free 释放动态数组的内存,并将相关指针和计数重置为0或NULL。遍历队列并打印函数 printQueue:
size 为0,打印队列为空的信息。front 和 rear 指针。主函数 main: