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;
}
相关推荐
GlobalTradercrb18 分钟前
展会获客和线上获客,预算先加给谁?答案看客单价
经验分享
C++ 老炮儿的技术栈31 分钟前
sizeof操作符
c语言·c++·人工智能·mfc·c
晚安日记wanna44 分钟前
MySQL 回表为什么这么慢?5 种优化手段逐个拆解
数据库·mysql·性能优化
第七页独白44 分钟前
汽车零件厂如何通过 QMS 真正落地 IATF 16949——QMS软件系统:品质检验-内审稽核-8d客诉管理:全星质量管理软件系统
java·前端·数据库
晚安日记wanna1 小时前
索引建了却不走?7 个失效原因逐层排查
数据库·mysql·性能优化
KID1412号1 小时前
PostgreSQL入门
数据库·postgresql
wuminyu1 小时前
ForkJoinPool内部WorkQueue的Lock-Free数组操作以及并发任务窃取原理剖析
java·linux·c语言·jvm·c++
Elastic 中国社区官方博客1 小时前
使用 Lucene 搜索你的 Bean — 索引
java·大数据·数据库·elasticsearch·搜索引擎·全文检索·lucene
code2cat1 小时前
Java进阶篇之AtomicMarkableReference:引用还在,标记已经改变
java·开发语言·cas·并发编程·逻辑删除
CappuccinoRose1 小时前
FormData数据处理
开发语言·前端·javascript·表单数据