概念
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
注意
1、队列是一种先进先出(First in First Out)的线性表,简称FIFO。
2、允许插入的一端称为队尾(rear),允许删除的一端称为队头(front)。
3、队列只允许在一端插入,在另一端删除。
4、最早进入队列的元素才能最先从队列中删除。
5、在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。
6、队列可分为顺序队列、链式队列、循环队列(可参见其它文章),循环队列可以提高队列空间的利用率,因此在实际应用中一般采用循环队列的方式。
7、队列可以使用数组和链表两种方式实现,数组的实现方式必须先确定栈的空间大小,相对而言,没有那么灵活,所以建议采用链表的方式实现。
核心
理解队列主要是理解队头、队尾、入队和出队。
队头(front):指向允许元素删除的一端。
队尾(rear):指向允许元素插入的一端。
入队(push):在队列中插入元素的操作。
![]()
出队(pop):在队列中删除元素的操作。
示例
★包含头文件queue_array.h和源文件queue_array.c(均已验证通过)。
queue_array.h
/** * @Filename : queue_array.h * @Revision : $Revision: 1.0 $ * @Author : Feng(微信公众号:不只会拍照的程序猿) * @Description : 顺序队列示例 **/ #ifndef __QUEUE_ARRAY_H__ #define __QUEUE_ARRAY_H__ #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 10 /* 队列结构定义 */ struct t_queue{ int buff[MAX_SIZE]; /* 保存队列元素 */ int front; /* 指向队头 */ int rear; /* 指向队尾 */ }; /** * @初始化队列 * @p_queue:队列 **/ void queue_init(struct t_queue *p_queue); /** * @删除队列 * @p_queue:队列 **/ void queue_deinit(struct t_queue *p_queue); /** * @判断队列是否已满 * @p_queue:队列 * @返回1表示已满,0表示未满 **/ int queue_is_full(const struct t_queue *p_queue); /** * @判断队列是否已空 * @p_queue:队列 * @返回1表示已空,0表示未空 **/ int queue_is_empty(const struct t_queue *p_queue); /** * @获取队列元素个数 * @p_queue:队列 * @返回元素个数 **/ int queue_get_size(const struct t_queue *p_queue); /** * @入队操作 * @p_queue:队列 data:队列元素 * @返回1表示成功,0表示失败 **/ int queue_push(struct t_queue *p_queue, int data); /** * @出队操作 * @p_queue:队列 data:队列元素 * @返回1表示成功,0表示失败 **/ int queue_pop(struct t_queue *p_queue, int *p_data); /** * @获取队头 * @p_queue:队列 p_data:保存队头元素 * @返回1表示成功,0表示失败 **/ int queue_get_front(const struct t_queue *p_queue, int *p_data); /** * @打印队列元素 * @p_queue:队列 **/ void queue_print(const struct t_queue *p_queue); #endif
queue_array.c
/** * @Filename : queue_array.c * @Revision : $Revision: 1.0 $ * @Author : Feng(微信公众号:不只会拍照的程序猿) * @Description : 顺序队列示例 **/ #include "queue_array.h" /** * @初始化队列 * @p_queue:队列 **/ void queue_init(struct t_queue *p_queue) { p_queue->front = 0; p_queue->rear = 0; } /** * @删除队列 * @p_queue:队列 **/ void queue_deinit(struct t_queue *p_queue) { p_queue->front = 0; p_queue->rear = 0; } /** * @判断队列是否已满 * @p_queue:队列 * @返回1表示已满,0表示未满 **/ int queue_is_full(const struct t_queue *p_queue) { return (p_queue->rear >= MAX_SIZE); } /** * @判断队列是否已空 * @p_queue:队列 * @返回1表示已空,0表示未空 **/ int queue_is_empty(const struct t_queue *p_queue) { return (p_queue->rear == p_queue->front); } /** * @获取队列元素个数 * @p_queue:队列 * @返回元素个数 **/ int queue_get_size(const struct t_queue *p_queue) { return (p_queue->rear - p_queue->front); } /** * @入队操作 * @p_queue:队列 data:队列元素 * @返回1表示成功,0表示失败 **/ int queue_push(struct t_queue *p_queue, int data) { // the queue is full, push failed if (p_queue->rear >= MAX_SIZE) { return 0; } p_queue->buff[p_queue->rear++] = data; return 1; } /** * @出队操作 * @p_queue:队列 data:队列元素 * @返回1表示成功,0表示失败 **/ int queue_pop(struct t_queue *p_queue, int *p_data) { // the queue is empty, pop failed if (p_queue->rear == p_queue->front) { return 0; } *p_data = p_queue->buff[p_queue->front]; p_queue->front++; return 1; } /** * @获取队头 * @p_queue:队列 p_data:保存队头元素 * @返回1表示成功,0表示失败 **/ int queue_get_front(const struct t_queue *p_queue, int *p_data) { // the queue is empty, pop failed if (p_queue->rear == p_queue->front) { return 0; } *p_data = p_queue->buff[p_queue->front]; return 1; } /** * @打印队列元素 * @p_queue:队列 **/ void queue_print(const struct t_queue *p_queue) { int i; for (i=p_queue->front; i<p_queue->rear; i++) printf("%d ", p_queue->buff[i]); printf("\n"); } /** * @顺序队列测试代码 **/ int main(void) { int data; struct t_queue my_queue; queue_init(&my_queue); /* 初始化队列,此时为空队列 */ printf("the queue is %s\n", queue_is_empty(&my_queue) ? "empty" : "not empty"); printf("---------------------------------------\n"); /* 入队,队列:25 41 16 7 8 19 22,元素个数为7 */ queue_push(&my_queue, 25); queue_push(&my_queue, 41); queue_push(&my_queue, 16); queue_push(&my_queue, 7); queue_push(&my_queue, 8); queue_push(&my_queue, 19); queue_push(&my_queue, 22); printf("the size of queue is: %d\n", queue_get_size(&my_queue)); queue_print(&my_queue); printf("---------------------------------------\n"); /* 入队35 38 11 22(队列已满,入队失败),队列:25 41 16 7 8 19 22 35 38 11,个数10 */ queue_push(&my_queue, 35); queue_push(&my_queue, 38); queue_push(&my_queue, 11); queue_push(&my_queue, 22); printf("the size of queue is: %d\n", queue_get_size(&my_queue)); queue_print(&my_queue); printf("the queue is %s\n", queue_is_full(&my_queue) ? "full" : "not full"); printf("---------------------------------------\n"); /* 队头元素为25,第一次出队25,第二次出队41,队列:16 7 8 19 22 35 38 11,个数8 */ if (queue_get_front(&my_queue, &data)) printf("the front queue data is: %d\n", data); if (queue_pop(&my_queue, &data)) printf("the pop queue data is: %d\n", data); if (queue_pop(&my_queue, &data)) printf("the pop queue data is: %d\n", data); printf("the size of queue is: %d\n", queue_get_size(&my_queue)); queue_print(&my_queue); printf("---------------------------------------\n"); /* 清除队列,个数0 */ queue_deinit(&my_queue); printf("the size of queue is: %d\n", queue_get_size(&my_queue)); return 0; }
结论
feng:queue$ gcc -o queue_array queue_array.c feng:queue$ ./queue_array the queue is empty --------------------------------------- the size of queue is: 7 25 41 16 7 8 19 22 --------------------------------------- the size of queue is: 10 25 41 16 7 8 19 22 35 38 11 the queue is full --------------------------------------- the front queue data is: 25 the pop queue data is: 25 the pop queue data is: 41 the size of queue is: 8 16 7 8 19 22 35 38 11 --------------------------------------- the size of queue is: 0 feng:queue$
本示例仅为顺序队列示例,公众号也提供链式队列示例《也没想象中那么神秘的数据结构-先来后到的“队列”(链式队列)》、循环队列示例《也没想象中那么神秘的数据结构-先来后到的“队列”(循环队列)》以及队列的典型应用示例。
关注
更多精彩内容,请关注微信公众号:不只会拍照的程序猿,本人致力分享linux、设计模式、C语言、嵌入式、编程相关知识,也会抽空分享些摄影相关内容,同样也分享大量摄影、编程相关视频和源码,另外你若想要本文章源码请关注公众号:不只会拍照的程序猿,后台回复:数据结构源码,也可点击此处下载。