队列的概念
在该文章数据结构 - 队列(顺序队列、单一数据类型)中讲述顺序的队列,本文则浅述一下链式队列。
链式队列的思路
链式队列实现起来会灵活很多,理论上是可以做到无限长的,出队入队也比较容易实现。本文所介绍的还是一种通用数据类型式的链式队列,使用上没有之前单一数据类型的那种复杂(要先定义个队列控制结构体,定义个数组,有控制体来完成数组的控制实现队列),而是可以定义int、float等类型队列,同样自定义的结构体类型的队列也可以。具体的实现思路参考数据结构 - 队列(顺序队列、单一数据类型)。
C语言代码
头文件
#ifndef __queue_H
#define __queue_H
/* 结点结构体定义 */
typedef struct _QUEUE_NODE_
{
struct _QUEUE_NODE_ *next;
void *data;
}QUEUE_NODE;
/* 队列结构体定义 */
typedef struct _QUEUE_
{
QUEUE_NODE *queue_head;
QUEUE_NODE *queue_tail;
unsigned int count;
unsigned char data_size;
unsigned int queue_size;
}QUEUE;
unsigned char queue_init(QUEUE *queue, unsigned char data_size, unsigned int queue_size);
unsigned char queue_empty(QUEUE *queue);
unsigned char queue_full(QUEUE *queue);
unsigned char queue_push(QUEUE *queue, void *data);
unsigned char queue_pop(QUEUE *queue, void *data);
void queue_clean(QUEUE *queue);
void queue_free(QUEUE *queue);
#endif
在“QUEUE”结构体内部已经定义好原来控制体所需要的成员,也增加“data_size”变量实现数据类型的通用。
源文件
#include "queue.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*********************************************************************************************************
** 函数名称: queue_init
** 功能描述: 队列初始化
** 输 入: queue: 队列
data_size: 数据域大小
queue_size: 队列长度大小 0-无限队列;其他-特定大小的循环队列
** 输 出: 1: 成功
0: 失败
********************************************************************************************************/
unsigned char queue_init(QUEUE *queue, unsigned char data_size, unsigned int queue_size)
{
unsigned int i = queue_size - 1; // 第一块不在循环内创建
QUEUE_NODE *temp_node = NULL;
QUEUE_NODE *last_node = NULL;
if (queue_size == 0) // 无限队列
{
queue->queue_head = NULL;
queue->queue_tail = NULL;
queue->data_size = data_size;
queue->count = 0;
queue->queue_size = queue_size;
}
else // 循环队列
{
// 创建第一块空间作为队头
temp_node = (QUEUE_NODE *)malloc(sizeof(QUEUE_NODE));
if (temp_node == NULL)
{
return 0;
}
temp_node->data = malloc(queue->data_size);
if (temp_node->data == NULL)
{
free(temp_node);
return 0;
}
queue->queue_head = temp_node;
while (i--) // 初始化每一块空间
{
// 获取前一个创建的
last_node = temp_node;
// 创建空间
temp_node = (QUEUE_NODE *)malloc(sizeof(QUEUE_NODE));
temp_node->data = malloc(queue->data_size);
last_node->next = temp_node;
}
// 首尾相连,形成循环
temp_node->next = queue->queue_head;
queue->queue_tail = NULL;
queue->data_size = data_size;
queue->count = 0;
queue->queue_size = queue_size;
}
return 1;
}
/*********************************************************************************************************
** 函数名称: queue_empty
** 功能描述: 判断队列是否为空
** 输 入: queue: 队列
** 输 出: 1: 为空
0: 非空
********************************************************************************************************/
unsigned char queue_empty(QUEUE *queue)
{
if (queue->count == 0)
{
return 1;
}
else
{
return 0;
}
}
/*********************************************************************************************************
** 函数名称: queue_full
** 功能描述: 判断队列是否满
** 输 入: queue: 队列
** 输 出: 1: 为满
0: 非满
********************************************************************************************************/
unsigned char queue_full(QUEUE *queue)
{
if (queue->queue_size != 0 && queue->count >= queue->queue_size)
{
return 1;
}
else
{
return 0;
}
}
/*********************************************************************************************************
** 函数名称: queue_push
** 功能描述: 入队操作
** 输 入: queue: 队列
data: 入队变量的地址
** 输 出: 1: 入队成功
0: 入队失败
********************************************************************************************************/
unsigned char queue_push(QUEUE *queue, void *data)
{
QUEUE_NODE *temp_node = NULL;
if (queue->queue_size == 0)
{
// 创建空间,赋值
temp_node = (QUEUE_NODE *)malloc(sizeof(QUEUE_NODE));
temp_node->data = malloc(queue->data_size);
memcpy(temp_node->data, data, queue->data_size);
temp_node->next = NULL;
// 更新队头队尾指针
if (queue->count == 0)
{
queue->queue_head = temp_node;
}
else
{
queue->queue_tail->next = temp_node;
}
queue->queue_tail = temp_node;
// 更新计数
queue->count++;
return 1;
}
else
{
// 判断队列是否满了
if (queue->count >= queue->queue_size)
{
return 0;
}
// 队尾指向空,表明刚初始化,队列为空
if(queue->queue_tail == NULL)
{
queue->queue_tail = queue->queue_head;
}
else
{
queue->queue_tail = queue->queue_tail->next;
}
// 赋值
memcpy(queue->queue_tail->data, data, queue->data_size);
// 更新计数
queue->count++;
return 1;
}
}
/*********************************************************************************************************
** 函数名称: queue_pop
** 功能描述: 出队操作
** 输 入: queue: 队列
data: 出队变量的地址
** 输 出: 1: 出队成功
0: 出队失败
********************************************************************************************************/
unsigned char queue_pop(QUEUE *queue, void *data)
{
QUEUE_NODE *temp_node = queue->queue_head;
// 判断队列是否为空
if (queue->count == 0)
{
return 0;
}
if (queue->queue_size == 0)
{
// 更新队头
queue->queue_head = queue->queue_head->next;
// 获取数据
memcpy(data, temp_node->data, queue->data_size);
// 释放空间
free(temp_node->data);
free(temp_node);
// 更新计数
queue->count--;
return 1;
}
else
{
// 更新队头
queue->queue_head = queue->queue_head->next;
// 获取数据
memcpy(data, temp_node->data, queue->data_size);
// 更新计数
queue->count--;
// 队列为空,让队尾指向空
if (queue->count == 0)
{
queue->queue_tail = NULL;
}
return 1;
}
}
/*********************************************************************************************************
** 函数名称: queue_clean
** 功能描述: 队列清空
** 输 入: queue: 队列
** 输 出: 无
********************************************************************************************************/
void queue_clean(QUEUE *queue)
{
QUEUE_NODE *temp_node = NULL;
if (queue->queue_size == 0)
{
// 循环删除
queue->count++;
while(--queue->count)
{
temp_node = queue->queue_head;
queue->queue_head = queue->queue_head->next;
free(temp_node->data);
free(temp_node);
}
queue->queue_tail = NULL;
}
else
{
queue->queue_tail = NULL;
queue->count = 0;
}
}
//
/*********************************************************************************************************
** 函数名称: queue_free
** 功能描述: 释放队列
** 输 入: queue: 队列
** 输 出: 无
********************************************************************************************************/
void queue_free(QUEUE *queue)
{
unsigned int i = 0;
QUEUE_NODE *temp_node = NULL;
i = queue->queue_size==0?queue->count:queue->queue_size;
// 针对循环队列释放创建的空间
while(i--)
{
temp_node = queue->queue_head;
queue->queue_head = queue->queue_head->next;
// 释放空间
free(temp_node->data);
free(temp_node);
}
queue->queue_head = NULL;
queue->queue_tail = NULL;
queue->data_size = 0;
queue->count = 0;
queue->queue_size = 0;
}
测试
#include <stdio.h>
#include "queue.h"
typedef struct
{
char name[12];
int heght;
float weight;
}STUDENT;
void print_student(STUDENT student)
{
printf("name: %s, height = %d, weight = %.2f\r\n", student.name, student.heght, student.weight);
}
int main()
{
int i = 0;
QUEUE queue;
QUEUE queue_stu;
int data = 0;
STUDENT student;
int queue_len = 0;
queue_init(&queue, sizeof(int), 10);
queue_init(&queue_stu, sizeof(STUDENT), 10);
for (i = 0; i < 11; i++)
{
data = i + 1;
queue_push(&queue, &data);
sprintf(student.name, "student%d", i);
student.heght = 170 + i;
student.weight = 60.5 + i;
queue_push(&queue_stu, &student);
}
queue_len = queue.count;
for (i = 0; i < queue_len; i++)
{
if (queue_pop(&queue, &data) == 1)
{
printf("pop<%d> = %d\r\n", i, data);
}
}
queue_len = queue_stu.count;
for (i = 0; i < queue_len; i++)
{
if (queue_pop(&queue_stu, &student) == 1)
{
print_student(student);
}
}
getchar();
return 0;
}
结果:
在初始化函数中,传入的变量“queue_size”还决定了队列的形式,传入0则为无限队列不限制队列长度,其他数则为特定长度的有限队列,并且在初始化时候完成空间分配。
建议: 这种链式的无限队列不建议在中断中使用,中断服务函数讲究快进快出,而链式队列每进一次队都要进行空间分配,会耗费很多的时间。
最后的最后,本人才疏学浅,此代码仅供参考交流,本人如有叙述错误,麻烦各位指正,有什么好的建议欢迎留言。