当前位置: 首页 > article >正文

C语言队列详解

一、什么是队列?

队列(Queue)是一种先进先出(FIFO, First In First Out)的线性数据结构。它只允许在一端插入数据(队尾),在另一端删除数据(队头)。常见于排队、消息缓冲等场景。

二、队列的结构定义

在C语言中,常用链式结构实现队列。每个节点包含数据域和指向下一个节点的指针。

// 队列节点结构体
typedef int QDataType;
​
typedef struct QueueNode {QDataType data;struct QueueNode* next;
} QueueNode;
​
// 队列结构体
typedef struct Queue {QueueNode* phead; // 队头指针QueueNode* ptail; // 队尾指针
} Queue;

三、队列的基本操作

1. 初始化队列

// 初始化队列
void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;
}

2. 销毁队列

// 销毁队列
void QueueDestory(Queue* pq)
{assert(pq);QueueNode* cur = pq->phead;while (cur){QueueNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;
}

3. 入队(队尾插入)

// 队尾入队列
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}
}

4. 出队(队头删除)

// 队头出队列
void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QueueNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}
}

5. 获取队列长度

// 获取队列中有效元素个数
int QueueSize(Queue* pq)
{assert(pq);// 如果频繁调用这个接口函数,可以在Queue中给一个size记录数据个数int n = 0;QueueNode* cur = pq->phead;while (cur){n++;cur = cur->next;}return n;
}

6. 获取队头元素

// 获取队列头部元素
QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->phead->data;
}

7. 获取队尾元素

// 获取队列队尾元素
QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->ptail->data;
}

8. 判断队列是否为空

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->ptail == NULL && pq->phead == NULL;
}

四、完整示例

头文件:

#pragma once
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QueueNode;typedef struct Queue
{QueueNode* phead;//头指针QueueNode* ptail;//尾指针
}Queue;
// 初始化队列
void QueueInit(Queue* pq);
// 销毁队列
void QueueDestory(Queue* pq);
// 队尾入队列
void QueuePush(Queue* pq, QDataType x);  // 队尾
// 队头出队列
void QueuePop(Queue* pq);                // 队头
// 获取队列中有效元素个数
int QueueSize(Queue* pq);
// 获取队列头部元素
QDataType QueueFront(Queue* pq);
// 获取队列队尾元素
QDataType QueueBack(Queue* pq);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq);

.c文件

#include "Queue.h"
// 初始化队列
void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;
}
// 销毁队列
void QueueDestory(Queue* pq)
{assert(pq);QueueNode* cur = pq->phead;while (cur){QueueNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;
}
// 队尾入队列
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}
}
// 队头出队列
void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QueueNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}
}
// 获取队列中有效元素个数
int QueueSize(Queue* pq)
{assert(pq);// 如果频繁调用这个接口函数,可以在Queue中给一个size记录数据个数int n = 0;QueueNode* cur = pq->phead;while (cur){n++;cur = cur->next;}return n;
}
// 获取队列头部元素
QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->phead->data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->ptail->data;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->ptail == NULL && pq->phead == NULL;
}

测试文件:

#include "Queue.h"int main()
{Queue q;QueueInit(&q);QueuePush(&q, 1);QueuePush(&q, 2);printf("%d ", QueueFront(&q));QueuePop(&q);QueuePush(&q, 3);QueuePush(&q, 4);while (!QueueEmpty(&q)){printf("%d ", QueueFront(&q));QueuePop(&q);}printf("\n");return 0;
}

五、注意事项与常见错误

  1. 内存管理:每次malloc后都要free,防止内存泄漏。

  2. 判空操作:出队、取队头/队尾元素前要判空,防止访问空指针。

  3. 队列长度:如需频繁获取队列长度,可在结构体中增加size成员,实时维护。

  4. 断言检查:操作前应检查指针有效性。

六、队列的应用场景

  • 任务调度、消息缓冲、广度优先搜索(BFS)、打印队列等。

七、总结

队列是一种常用的数据结构,适合需要按顺序处理数据的场景。掌握其链式实现原理和常见操作,有助于更好地理解数据结构和C语言指针操作。

http://www.lryc.cn/news/2387617.html

相关文章:

  • Qt中的智能指针
  • 车载网关策略 --- 车载网关通信故障处理机制深度解析
  • 三天掌握PyTorch精髓:从感知机到ResNet的快速进阶方法论
  • Python爬虫实战:研究Selenium框架相关技术
  • 分布式缓存:三万字详解Redis
  • BiLSTM与Transformer:位置编码的隐式vs显式之争
  • html5视频播放器和微信小程序如何实现视频的自动播放功能
  • 【QT】QString和QStringList去掉空格的方法总结
  • 58同城大数据面试题及参考答案
  • 25.5.27学习总结
  • 关于vue结合elementUI输入框回车刷新问题
  • vue项目表格甘特图开发
  • Spark 中,创建 DataFrame 的方式(Scala语言)
  • Python----目标检测(MS COCO数据集)
  • 塔能科技:有哪些国内工业节能标杆案例?
  • 图论:floyed算法
  • 嵌入式系统C语言编程常用设计模式---参数表驱动设计
  • OpenCV CUDA模块图像过滤------创建一个行方向的一维积分(Sum)滤波器函数createRowSumFilter()
  • Frequent values/gcd区间
  • 08SpringBoot高级--自动化配置
  • Deep Evidential Regression
  • 「Python教案」循环语句的使用
  • linux快速入门-VMware安装linux,配置静态ip,使用服务器连接工具连接,快照和克隆以及修改相关配置信息
  • 用户配置文件(Profile)
  • ubuntu 制作 ssl 证书
  • Vue组件技术全解析大纲
  • 轻量化开源方案——浅析PdfPatcher实际应用
  • Ansible常用Ad-Hoc 命令
  • [论文阅读]Pandora: Jailbreak GPTs by Retrieval Augmented Generation Poisoning
  • 鸿蒙OSUniApp 制作个性化的评分星级组件#三方框架 #Uniapp