设计链式队列代码

设计链式队列代码

Notice!!!:

  • 在处理入队时一定要进行判断队列是否为空,因为我们在链式队列初始化的时候将Manager->front = NULL; Manager->rear = NULL;这俩指向了NULL。
  • 如果不进行这段处理,当队列最初为空时,Manager->rearManager->front都是NULL。此时执行Manager->rear->next = newNode;语句,就会通过空指针Manager->rear去访问它的成员next,这是非法的内存访问,会导致段错误,程序会异常终止。
    image
/********************************************************************************************************
 *
 * 该程序实现链式队列元素的增删改查,目的是提高设计程序的逻辑思维,另外为了提高可移植性,所以链式队列中元素
 * 的数据类型为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;
}

测试结果展示

image

posted @ 2025-05-12 21:14  Arroyol  阅读(16)  评论(0)    收藏  举报