设计链式队列代码
Notice!!!:
- 在处理入队时一定要进行判断队列是否为空,因为我们在链式队列初始化的时候将
Manager->front = NULL; Manager->rear = NULL;
这俩指向了NULL。
- 如果不进行这段处理,当队列最初为空时,
Manager->rear
和Manager->front
都是NULL
。此时执行Manager->rear->next = newNode;
语句,就会通过空指针Manager->rear
去访问它的成员next
,这是非法的内存访问,会导致段错误,程序会异常终止。

/********************************************************************************************************
*
* 该程序实现链式队列元素的增删改查,目的是提高设计程序的逻辑思维,另外为了提高可移植性,所以链式队列中元素
* 的数据类型为DataType_t,用户可以根据实际情况修改链式队列中元素的类型。
*
* 另外,为了方便管理链式队列,所以设计LinkQueue_t结构体,该结构体中包含二个成员:队首地址+队尾地址
* 同时定义单个链表节点的结构体,包括数据域以及next指针。
*
* Copyright (c) 2023-2024 xu1234xcs@126.com All right Reserved
* ******************************************************************************************************/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
// 指的是链式队列中的元素的数据类型,用户可以根据需要进行修改
typedef int DataType_t;
typedef struct LinkNode
{
DataType_t data; // 存储栈中元素的数据域
struct LinkNode *next; // 指向下一个节点的指针(链式队的下一层)
} LinkNode_t;
// 构造记录链式队列CircularQueue各项参数(链式队列的队尾地址 + 链式队列的容量 )的结构体
typedef struct LinkQueue
{
LinkNode_t *front; // 记录链式队列队首地址
LinkNode_t *rear; // 记录链式队列队尾地址
} LinkQueue_t;
// 创建链式队列并对链式队列进行初始化
LinkQueue_t *LinkQueue_Create()
{
// 1.利用calloc为链式队列的管理结构体申请一块堆内存
LinkQueue_t *Manager = (LinkQueue_t *)calloc(1, sizeof(LinkQueue_t));
if (NULL == Manager)
{
perror("calloc memory for manager is failed");
exit(-1); // 程序异常终止
}
// 2.对管理链式队的结构体进行初始化(元素容量 + 最后元素下标)
Manager->front = NULL;
Manager->rear = NULL;
return Manager;
}
// 初始化一个新的链式队列节点
LinkNode_t *LinkNode_Create(DataType_t Data)
{
// 1.利用calloc为链式栈的新节点申请一块堆内存
LinkNode_t *new = (LinkNode_t *)calloc(1, sizeof(LinkNode_t));
if (NULL == new)
{
perror("calloc memory for manager is failed");
exit(-1); // 程序异常终止
}
// 2.对管理链式队列的新节点进行初始化(元素容量 + 最后元素下标)
new->data = Data;
new->next = NULL;
return new;
}
// 入队
bool LinkQueue_Enqueue(LinkQueue_t *Manager, DataType_t Data)
{
// 1.创建新节点
LinkNode_t *newNode = LinkNode_Create(Data);
if (NULL == newNode)
{
perror("calloc memory for manager is failed");
exit(-1); // 程序异常终止
}
// 处理队列为空的情况
if (Manager->rear == NULL)
{
Manager->front = newNode;
Manager->rear = newNode;
}
else
{
Manager->rear->next = newNode;
Manager->rear = newNode;
}
return true;
}
// 判断链式队列是否为空
bool LinkQueue_IsEmpty(LinkQueue_t *Manager)
{
return (Manager->front == NULL);
}
// 出队
DataType_t LinkQueue_Dequeue(LinkQueue_t *Manager)
{
DataType_t temp;
// 1.判断链式队列是否为空
if (LinkQueue_IsEmpty(Manager))
{
printf("LinkQueue is Empty!\n");
return -1;
}
// 2.备份队首元素值
temp = Manager->front->data;
// 3.保存队首节点指针
LinkNode_t *tempNode = Manager->front;
// 4.更新队首指针
Manager->front = Manager->front->next;
// 处理队列为空的情况
if (Manager->front == NULL)
{
Manager->rear = NULL;
}
// 5.释放原队首节点内存
free(tempNode);
return temp;
}
int main(int argc, char const *argv[])
{
LinkQueue_t *manger = LinkQueue_Create();
LinkQueue_Enqueue(manger, 10);
LinkQueue_Enqueue(manger, 20);
LinkQueue_Enqueue(manger, 30);
LinkQueue_Enqueue(manger, 40);
LinkQueue_Enqueue(manger, 50);
// 出队测试
while (!LinkQueue_IsEmpty(manger))
{
DataType_t dequeuedData = LinkQueue_Dequeue(manger);
printf("Dequeued data: %d\n", dequeuedData);
}
return 0;
}
测试结果展示
