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;
}
相关推荐
weifexie23 分钟前
ruby可变参数
开发语言·前端·ruby
王磊鑫24 分钟前
重返JAVA之路-初识JAVA
java·开发语言
千野竹之卫24 分钟前
3D珠宝渲染用什么软件比较好?渲染100邀请码1a12
开发语言·前端·javascript·3d·3dsmax
woshilys1 小时前
mysql 删除表等待
数据库·mysql
liuluyang5301 小时前
C语言C11支持的结构体嵌套的用法
c语言·开发语言·算法·编译·c11
凌叁儿1 小时前
python保留关键字详解
开发语言·python
SEO-狼术2 小时前
dbForge Documenter for Oracle Crack
数据库·oracle
明飞19872 小时前
C_内存 内存地址概念
c语言·开发语言
勤劳的进取家2 小时前
贪心算法之最小生成树问题
数据结构·python·算法·贪心算法·排序算法·动态规划
代码不停2 小时前
Java中的异常
java·开发语言