C 语言的标准库(C Standard Library, 即 libc)本身并没有直接提供一个名为 queue.h 的通用队列头文件,与 stdio.h(输入输出)、stdlib.h(内存分配、随机数等)或 string.h(字符串操作)不同,队列是一种数据结构,而不是语言的基本功能。

(图片来源网络,侵删)
在 C 语言中实现队列通常有以下几种主要方式,每种方式都依赖不同的头文件:
使用标准库的链表实现(最常见)
这是在 C 语言中实现队列最灵活、最常用的方法,我们利用标准库中的双向链表 (struct list_head) 来构建队列,这种方法的好处是标准库已经为我们实现了链表的核心操作(插入、删除、遍历),我们只需要封装成队列的“入队”和“出队”接口即可。
核心头文件
<stddef.h>: 定义了NULL、size_t等常用宏和类型。<stdbool.h>: (C99 引入) 定义了bool、true、false类型,使代码更易读。<stdlib.h>: 提供了malloc和free用于动态内存分配。
关键结构
<linux/list.h> (或其跨平台版本) 是实现这一方式的核心,虽然它源于 Linux 内核,但其思想被广泛用于用户空间的 C 程序,为了演示,这里我们实现一个简化版的链表队列。
完整代码示例
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 1. 定义队列节点结构
typedef struct QueueNode {
int data; // 数据域
struct QueueNode* next; // 指针域,指向下一个节点
} QueueNode;
// 2. 定义队列结构
typedef struct {
QueueNode* front; // 队头指针
QueueNode* rear; // 队尾指针
int size; // 队列大小(可选)
} Queue;
// 3. 初始化队列
void initQueue(Queue* q) {
q->front = q->rear = NULL;
q->size = 0;
}
// 4. 检查队列是否为空
bool isEmpty(Queue* q) {
return q->front == NULL;
}
// 5. 入队
void enqueue(Queue* q, int value) {
// 创建新节点
QueueNode* newNode = (QueueNode*)malloc(sizeof(QueueNode));
if (newNode == NULL) {
printf("内存分配失败!\n");
exit(1);
}
newNode->data = value;
newNode->next = NULL;
if (isEmpty(q)) {
// 如果队列为空,新节点既是队头也是队尾
q->front = q->rear = newNode;
} else {
// 否则,将新节点添加到队尾,并更新队尾指针
q->rear->next = newNode;
q->rear = newNode;
}
q->size++;
}
// 6. 出队
int dequeue(Queue* q) {
if (isEmpty(q)) {
printf("错误:队列为空,无法出队!\n");
exit(1); // 或者返回一个特殊值,如 INT_MIN
}
QueueNode* temp = q->front;
int value = temp->data;
q->front = q->front->next;
free(temp);
// 如果出队后队列为空,需要将队尾指针也置为 NULL
if (q->front == NULL) {
q->rear = NULL;
}
q->size--;
return value;
}
// 7. 获取队头元素(不删除)
int peek(Queue* q) {
if (isEmpty(q)) {
printf("错误:队列为空!\n");
exit(1);
}
return q->front->data;
}
// 8. 销毁队列,释放所有内存
void destroyQueue(Queue* q) {
while (!isEmpty(q)) {
dequeue(q);
}
}
// 9. 打印队列
void printQueue(Queue* q) {
QueueNode* current = q->front;
printf("Queue: [");
while (current != NULL) {
printf("%d", current->data);
if (current->next != NULL) {
printf(", ");
}
current = current->next;
}
printf("]\n");
}
int main() {
Queue myQueue;
initQueue(&myQueue);
enqueue(&myQueue, 10);
enqueue(&myQueue, 20);
enqueue(&myQueue, 30);
printQueue(&myQueue); // 输出: Queue: [10, 20, 30]
printf("Dequeued: %d\n", dequeue(&myQueue)); // 输出: Dequeued: 10
printf("Front element: %d\n", peek(&myQueue)); // 输出: Front element: 20
printQueue(&myQueue); // 输出: Queue: [20, 30]
destroyQueue(&myQueue);
return 0;
}
使用标准库的动态数组实现
这种方式使用 C 标准库中的 <stdlib.h> 来管理一块连续的内存空间,模拟循环队列。

(图片来源网络,侵删)
核心头文件
<stdlib.h>: 提供malloc,free,realloc。<stdbool.h>: 用于bool类型。
特点
- 优点: 数据在内存中连续,缓存友好,访问效率高。
- 缺点: 大小固定(除非使用
realloc动态扩容,效率较低),实现循环队列逻辑稍微复杂。
代码片段(简化版)
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define INITIAL_CAPACITY 4
typedef struct {
int* items; // 存储数据的数组
int front; // 队头索引
int rear; // 队尾索引
int capacity; // 数组总容量
int size; // 当前元素个数
} ArrayQueue;
void initArrayQueue(ArrayQueue* q) {
q->capacity = INITIAL_CAPACITY;
q->items = (int*)malloc(q->capacity * sizeof(int));
q->front = 0;
q->rear = -1; // 通常初始为 -1
q->size = 0;
}
bool isFull(ArrayQueue* q) {
return q->size == q->capacity;
}
void enqueue(ArrayQueue* q, int value) {
if (isFull(q)) {
// 这里应该实现扩容逻辑,省略...
printf("Queue is full!\n");
return;
}
q->rear = (q->rear + 1) % q->capacity; // 循环
q->items[q->rear] = value;
q->size++;
}
// ... (dequeue, peek, destroy 等函数)
使用第三方库
如果你不想自己实现,可以使用成熟的第三方 C 语言数据结构库,这些库通常会提供完整的、经过测试的队列实现。
著名的第三方库
-
GLib (G Object Library):
-
头文件:
<glib.h> -
简介: GTK 等项目的基础库,提供了非常丰富的数据结构,包括
GQueue。
(图片来源网络,侵删) -
示例:
#include <glib.h> int main() { GQueue* queue = g_queue_new(); g_queue_push_tail(queue, "first"); g_queue_push_tail(queue, "second"); char* item = (char*)g_queue_pop_head(queue); printf("Popped: %s\n", item); // Popped: first g_free(item); g_queue_free(queue); return 0; } -
优点: 功能强大,稳定,跨平台。
-
缺点: 需要额外安装和链接库。
-
-
CSTL (C++ Standard Library for C):
- 头文件:
<cstl/queue.h> - 简介: 试图在 C 语言中模拟 C++ STL 的风格,提供了
queue容器。 - 优点: 接口接近 C++ STL,对熟悉 C++ 的开发者友好。
- 头文件:
总结与对比
| 实现方式 | 核心头文件 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
| 链表实现 | <stdlib.h>, <stdbool.h> |
动态大小,灵活,内存利用率高 | 需要手动管理内存,有额外指针开销 | 通用,元素数量不固定,是 C 语言中最常见的实现方式。 |
| 动态数组实现 | <stdlib.h>, <stdbool.h> |
数据连续,缓存友好,访问快 | 大小固定或扩容成本高,实现逻辑稍复杂 | 元素数量大致固定,或对访问性能要求极高。 |
| 第三方库 | <glib.h> 等 |
功能完善,稳定,经过测试 | 需要依赖外部库,增加项目复杂度 | 项目中已使用相关库(如 GTK),或追求快速开发和可靠性。 |
如果你想在纯 C 语言环境中实现一个队列,没有所谓的 queue.h,你应该:
- 首选自己动手用链表实现:这是最标准、最灵活的方式,只需要
<stdlib.h>和<stdbool.h>。 - 如果项目允许或已经在使用,考虑使用 GLib 这样的第三方库,可以节省开发时间并提高代码质量。
