数据结构之队列
一、队列是什么
队列是一种可以实现“先进先出”的存储结构。其实,说简单点,队列就是排队,跟我们日常生活中到银行取钱排队,排队打饭在道理上是一样的。
队列通常可以分为两种类型:
①链式队列(由链表实现)。
②静态队列(由数组实现),静态队列通常都必须是循环队列。
由于链式队列跟链表差不多,所以在这里只针对循环队列来说明并实践。
循环队列的两个参数:
①front,front指向队列的第一个元素。
②rear,rear指向队列的最后一个有效元素的下一元素。
队列的两个基本操作:出队和入队。
二、队列的结构
下面是一个循环队列(基于数组实现)的结构图:
三、队列的操作
1>入队(尾部入队)
①将值存入rear所代表的位置。
②rear = (rear+1)%数组的长度。
2>出队(头部出队)
front = (front+1)%数组的长度。
3>队列是否为空
front和rear的值相等,则该队列就一定为空。
4>队列是否已满
注意:循环队列中,有n个位置,通常放n-1个值,空1个
在循环队列中,front和rear指向的值不相关,无规律。front可能比rear指向的值大,也可能比rear指向的值小,也可能两者相等。
5>算法:
①多增加一个标识参数。
②少用一个元素,rear和front指向的值紧挨着,则队列已满。
四、队列的实现
基于数组的循环队列的具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | #include<stdio.h> #include<malloc.h> //包含了malloc函数 /* *循环队列,用数组实现 */ //队列结构体定义 typedef struct Queue { int * pBase; //用于动态分配内存,pBase保存数组的首地址 int front; //指向头结点 int rear; //指向最后一个元素的下一结点 } QUEUE; <br> //函数声明 void initQueue(QUEUE * pQueue); //队列初始化的函数 bool isEmpty(QUEUE * pQueue); //判断队列是否为空的函数 bool isFull(QUEUE * pQueue); //判断队列是否满的函数 bool enQueue(QUEUE * pQueue, int value); //入队的函数 bool outQueue(QUEUE * pQueue, int * pValue); //出队的函数,同时保存出队的元素 void traverseQueue(QUEUE * pQueue); //遍历队列的函数 <br> /* *主程序 */ int main( void ) { int value; //用于保存出队的元素 //创建队列对象 QUEUE queue; //调用初始化队列的函数 initQueue(&queue); //调用出队函数 enQueue(&queue, 1); enQueue(&queue, 2); enQueue(&queue, 3); enQueue(&queue, 4); enQueue(&queue, 5); enQueue(&queue, 6); enQueue(&queue, 7); enQueue(&queue, 8); //调用遍历队列的函数 traverseQueue(&queue); //调用出队函数 if (outQueue(&queue, &value)) { printf ( "出队一次,元素为:%d\n" , value); } traverseQueue(&queue); if (outQueue(&queue, &value)) { printf ( "出队一次,元素为:%d\n" , value); } traverseQueue(&queue); getchar (); return 0; } /* *初始化函数的实现 */ void initQueue(QUEUE * pQueue) { //分配内存 pQueue->pBase = ( int *) malloc ( sizeof ( int ) * 6); //分配6个int型所占的空间 pQueue->front = 0; //初始化时,front和rear值均为0 pQueue->rear = 0; return ; } /* *入队函数的实现 */ bool enQueue(QUEUE * pQueue, int value) { if (isFull(pQueue)) { printf ( "队列已满,不能再插入元素了!\n" ); return false ; } else { //向队列中添加新元素 pQueue->pBase[pQueue->rear] = value; //将rear赋予新的合适的值 pQueue->rear = (pQueue->rear+1) % 6; return true ; } } /* *出队函数的实现 */ bool outQueue(QUEUE * pQueue, int * pValue) { //如果队列为空,则返回false if (isEmpty(pQueue)) { printf ( "队列为空,出队失败!\n" ); return false ; } else { *pValue = pQueue->pBase[pQueue->front]; //先进先出 pQueue->front = (pQueue->front+1) % 6; //移到下一位置 return true ; } } /* *遍历队列的函数实现 */ void traverseQueue(QUEUE * pQueue) { int i = pQueue->front; //从头开始遍历 printf ( "遍历队列:\n" ); while (i != pQueue->rear) //如果没有到达rear位置,就循环 { printf ( "%d " , pQueue->pBase[i]); i = (i+1) % 6; //移到下一位置 } printf ( "\n" ); return ; } /* *判断队列是否满的函数的实现 */ bool isFull(QUEUE * pQueue) { if ((pQueue->rear+1) % 6 == pQueue->front) //队列满 return true ; else return false ; } /* *判断队列是否为空函数的实现 */ bool isEmpty(QUEUE * pQueue) { if (pQueue->front == pQueue->rear) return true ; else return false ; } |
五、队列的应用
在我们去打饭的时候总要排队,排队是与时间有关的,排在前面的人多,我们打到饭用的时间就比较长,相反,如果前面的排队的人相对较少,我们能打到饭的用的时间也就相对较短,所以说,队列总是与时间相关的。可以肯定地说:任何与时间相关的操作,基本上都会牵扯到队列。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)