C语言队列的实现

目录

​编辑

(一)队列的定义,初始化及创建结点

(二)入队和出队,以及取队头队尾的数据

(三)销毁队列


队列是指只允许在一端进行插入数据操作,在另⼀端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的特点。本篇文章的队列以链表为基础进行创建


(一)队列的定义,初始化及创建结点

复制代码
//队列的初始化
//我们先宏定义队列存储的数据类型

#define QueueDataType int           //这里我们宏定义队列存储的数据类型为int

//这里定义队列的结点
typedef struct QueueNode
{
    QueueDataType data;
    struct QueueNode* next;
}QueueNode;

//为了方便队列的出队和入队我们要新定义一个结构体,里面装着头结点和尾结点的指针。
type struct Queue
{
    QueueNode* phead;
    QueueNode* ptail;
}Queue;

这里我们定义了队列的结点和管理整个队列的结构体。关于链表形式的数据结构我们往往要单独写封装一个函数来创建结点。

复制代码
//封装一个函数,专门用来创建结点
//该函数的形参是一个数据类型,返回创建的结点的指针
QueueNode* BuyNewNode(QueueDataType val)
{
    //动态向内存申请空间
    QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
    //防止使用创建结点失败返回的NULL指针
    if (newnode == NULL)
    {
        perror("newnode malloc failed!");
        exit(1);
    }
    //给创建好的结点初始化
    newnode->data = val;
    newnode->next = NULL;

    //返回初始值
    return newnode;
}

我们还需要初始化管理整个结点的那个结构体,就叫它队列吧

复制代码
//初始化队列
void InitQueue(Queue* pq)
{
    //检查是否为空指针
    assert(pq);
    pq->phead = NULL;
    pq->ptail = NULL;
}

(二)入队和出队,以及取队头队尾的数据

入队就是从队伍的后面进去。根据这个原理我们直接写

复制代码
//队列的入队(要在初始化队列之后)
//我们通过管理整个队列的那个结构体来进行操作
//所以这里我们接受那个结构体的形参
void QueuePush(Queue* pq, QueueDataType val)
{
    //检查是不是空指针
    assert(pq);
    //我们可以通过pq来找到队伍的尾结点
    //进行入队操作。如果队列为空
    if (pq->phead == NULL)
    {
        pq->phead = pq->ptail = BuyNewNode(val);
    }
    else                //如果队列不为空,则尾插到队尾
    {
        pq->ptail->next = BuyNewNode(val);
        pq->ptail = pq->ptail->next;
    }
}

在写出队之前我们先得写一个函数来检查队列是否为空,防止队列里没有数据

复制代码
//判断队列是否为空,我们采用bool值
bool QueueEmpty(Queue* pq)
{
    assert(pq);
    return pq->phead == NULL;
}

进行出队。

复制代码
//队列的出队
void QueuePop(Queue* pq)
{    
    //检查队列是否为空
    assert(!QueueEmpty(pq));
    //如果队列只有一个元素
    if (pq->phead == pq->ptail)
    {
        pq->phead = pq->ptail = NULL;
    }
    else
    {    
        //定义一个新结点来保存出队后的头结点
        QueueNode* ptem = pq->phead->next;
        free(pq->phead); 
        pq->phead = ptem;
    }
}    

取队头就很简单了,也是直接写

复制代码
//取队头
QueueDataType QueueFront(Queue* pq)
{
    //检查队列是否为空
    assert(!QueueEmpty(pq));
    return pq->phead->data;
}

取队尾更是无需多言

复制代码
//取队尾的数据    
void QueueBack(Queue* pq)
{
    assert(!QueueEmpty(pq));
    return pq->ptail->data;
}

(三)销毁队列

最后的环节也必然是我们的销毁队列

复制代码
//销毁队列    
void QueueDestroy(Queue* pq)
{
    assert(pq);
    //新定义一个结点用来遍历队列
    QueueNode* pcur = pq->phead;
    //开始遍历链表销毁
    while (pcur)
    {    
        //再新定义一个结点来保存下一个节点
        QueueNode* ptem = pcur->next;
        free(pcur);
        pcur = ptem;
    }
    pq->phead = pq->ptail = NULL;
}
相关推荐
小汉堡编程2 小时前
数据结构——vector数组c++(超详细)
数据结构·c++
Hello.Reader4 小时前
Redis 延迟监控深度指南
数据库·redis·缓存
ybq195133454314 小时前
Redis-主从复制-分布式系统
java·数据库·redis
weixin_472339465 小时前
高效处理大体积Excel文件的Java技术方案解析
java·开发语言·excel
枯萎穿心攻击5 小时前
响应式编程入门教程第二节:构建 ObservableProperty<T> — 封装 ReactiveProperty 的高级用法
开发语言·unity·c#·游戏引擎
雾里看山5 小时前
顺序表VS单链表VS带头双向循环链表
数据结构·链表
Eiceblue7 小时前
【免费.NET方案】CSV到PDF与DataTable的快速转换
开发语言·pdf·c#·.net
好奇的菜鸟7 小时前
如何在IntelliJ IDEA中设置数据库连接全局共享
java·数据库·intellij-idea
tan180°7 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
m0_555762907 小时前
Matlab 频谱分析 (Spectral Analysis)
开发语言·matlab