概念
关于队列的相关内容,在之前的文章已经详细介绍过了,请参见《也没想象中那么神秘的数据结构-先来后到的“队列”(顺序队列)》,本文主要将链式队列相关内容。
链式队列:链式队列是基于单链表的存储表示实现的队列,其本质就是线性表的单链表,只不过它只能尾进头出而已。
核心
队列的结构:队列包含两个指针,p_front指向头节点,p_rear指向尾节点,另外头节点固定不变,数据域内容任意指定,一般设定为队列长度。
队列为空的时候,p_front和p_rear均指向头节点,队列不为空的时候,各节点之间通过指针一环扣一环连接起来。
入队:在队尾节点之后插入新节点的操作,插入的时候注意队头指针不变,队尾指针需要改变指针指向。
出队:删除头结点的后继节点,出队的时候注意头结点指针指向的改变。
示例
★包含头文件queue_list.h和源文件queue_list.c(均已验证通过)。
queue_list.h
/** * @Filename : queue_list.h * @Revision : $Revision: 1.0 $ * @Author : Feng(微信公众号:不只会拍照的程序猿) * @Description : 链式队列示例 **/ #ifndef __QUEUE_LIST_H__ #define __QUEUE_LIST_H__ #include <stdio.h> #include <stdlib.h> #define MAX_SIZE 10 /* 队列最大元素个数 */ /* 队列节点元素定义 */ struct t_node{ int data; /* 元素值 */ struct t_node *p_next; /* 指向下一个元素 */ }; /* 队列空间定义 */ struct t_queue{ struct t_node *p_front; /* 指向队头 */ struct t_node *p_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:队列 p_data:保存出队列元素 * @返回1表示成功,0表示失败 **/ int queue_pop(struct t_queue *p_queue, int *p_data); /** * @获取队列顶元素 * @p_queue:队列 p_data:保存队列顶元素 * @返回1表示成功,0表示失败 **/ int queue_get_top(const struct t_queue *p_queue, int *p_data); /** * @打印队列元素内容 * @p_queue:队列 **/ void queue_print(const struct t_queue *p_queue); #endif
queue_list.c
/** * @Filename : queue_list.c * @Revision : $Revision: 1.0 $ * @Author : Feng(微信公众号:不只会拍照的程序猿) * @Description : 链式队列示例 **/ #include "queue_list.h" /** * @创建节点 * @data:元素值 * @返回节点地址,NULL表示失败 **/ static struct t_node *creat_node(int data) { struct t_node *p_node = (struct t_node *)malloc(sizeof(struct t_node)); if (p_node == NULL) return NULL; p_node->data = data; p_node->p_next = NULL; return p_node; } /** * @初始化队列 * @p_queue:队列 * @创建头结点,让队头和队尾均指向头结点,头结点数据存储队列长度 **/ void queue_init(struct t_queue *p_queue) { struct t_node *p_head = creat_node(0); /* 头结点 */ if (p_head == NULL) return; p_queue->p_front = p_queue->p_rear = p_head; } /** * @清除队列 * @p_queue:队列 **/ void queue_deinit(struct t_queue *p_queue) { struct t_node *p_tmp = NULL, *p_node = p_queue->p_front->p_next; while(p_node) { p_tmp = p_node; p_node = p_node->p_next; free(p_tmp); } p_queue->p_rear = p_queue->p_front; p_queue->p_front->data = 0; } /** * @判断队列是否已满 * @p_queue:队列 * @返回1表示已满,0表示未满 **/ int queue_is_full(const struct t_queue *p_queue) { return (p_queue->p_front->data >= MAX_SIZE); } /** * @判断队列是否已空 * @p_queue:队列 * @返回1表示已空,0表示未空 **/ int queue_is_empty(const struct t_queue *p_queue) { return (p_queue->p_front->data == 0); } /** * @获取队列元素个数 * @p_queue:队列 * @返回元素个数 **/ int queue_get_size(const struct t_queue *p_queue) { return (p_queue->p_front->data); } /** * @入队列操作 * @p_queue:队列 data:待插入元素 * @返回1表示成功,0表示失败 **/ int queue_push(struct t_queue *p_queue, int data) { struct t_node *p_node = NULL; if (queue_is_full(p_queue)) return 0; if ((p_node = creat_node(data)) == NULL) return 0; p_queue->p_rear->p_next = p_node; p_queue->p_rear = p_node; p_queue->p_front->data++; return 1; } /** * @出队列操作 * @p_queue:队列 p_data:保存出队列元素 * @返回1表示成功,0表示失败 **/ int queue_pop(struct t_queue *p_queue, int *p_data) { struct t_node *p_node = NULL; if (queue_is_empty(p_queue)) return 0; p_node = p_queue->p_front->p_next; p_queue->p_front->p_next = p_node->p_next; *p_data = p_node->data; free(p_node); p_queue->p_front->data--; return 1; } /** * @获取队列顶元素 * @p_queue:队列 p_data:保存队列顶元素 * @返回1表示成功,0表示失败 **/ int queue_get_top(const struct t_queue *p_queue, int *p_data) { if (queue_is_empty(p_queue)) return 0; *p_data = p_queue->p_front->p_next->data; return 1; } /** * @打印队列元素内容 * @p_queue:队列 **/ void queue_print(const struct t_queue *p_queue) { struct t_node *p_node = p_queue->p_front->p_next; while(p_node) { printf("%d ", p_node->data); p_node = p_node->p_next; } 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"); /* 队列顶元素为11,第一次出队列11,第二次出队列38,队列:25 41 16 7 8 19 22 35,个数8 */ if (queue_get_top(&my_queue, &data)) printf("the top 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_list queue_list.c feng:queue$ ./queue_list 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 top 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语言、嵌入式、编程相关知识,也会抽空分享些摄影相关内容,同样也分享大量摄影、编程相关视频和源码,另外你若想要本文章源码请关注公众号:不只会拍照的程序猿,后台回复:数据结构源码,也可点击此处下载。