本网站(662p.com)打包出售,且带程序代码数据,662p.com域名,程序内核采用TP框架开发,需要联系扣扣:2360248666 /wx:lianweikj
精品域名一口价出售:1y1m.com(350元) ,6b7b.com(400元) , 5k5j.com(380元) , yayj.com(1800元), jiongzhun.com(1000元) , niuzen.com(2800元) , zennei.com(5000元)
需要联系扣扣:2360248666 /wx:lianweikj
C语言数据结构与算法之队列的实现详解
zhuxiaoqiang · 153浏览 · 发布于2022-10-18 +关注

队列只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的原则。本文将通过实例详细说说队列的实现,需要的可以学习一下


队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)的原则

入队列:进行插入操作的一端称为队尾

出队列:进行删除操作的一端称为队头

队列的结构在生活中非常地常见,比如排队时的抽号机就是一个典型的队列结构。那队列如何实现呢?我们一起来看一下。

队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些。因为如果使用数组的结构,出队列在数组头上出数据,需要挪动数据,时间复杂度为O(N),效率会比较低。

Queue.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
 
typedef int QDataType;
typedef struct QueueNode
{
    QDataType data;
    struct QueueNode* next;
}QNode;
 
typedef struct Queue
{
    QNode* head; // 头指针
    QNode* tail; // 尾指针
    int size;    // 节点的个数
}Queue;
 
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDataType x);
void QueuePop(Queue* pq);
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);

队列要实现的函数接口有:初始化队列、销毁队列、数据入队、数据出队、返回队头的数据、返回队尾的数据、判断队列是否为空以及队列中数据的个数。这些接口实现起来也不是很难,我们一起来看一下。

Queue.c

#include "Queue.h"
 void QueueInit(Queue* pq)
{
    assert(pq);
    pq->head = pq->tail = NULL;
    pq->size = 0;
}
 void QueueDestroy(Queue* pq)
{
    assert(pq);
     QNode* cur = pq->head;
    while (cur)
    {
        QNode* del = cur;
        cur = cur->next;
        free(del);
    }
     pq->head = pq->tail = NULL;
    pq->size = 0;
}
 void QueuePush(Queue* pq, QDataType x)
{
    assert(pq);
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    else
    {
        newnode->data = x;
        newnode->next = NULL;
    }
     // 队列中没有节点
    if (pq->tail == NULL)
    {
        pq->head = pq->tail = newnode;
    }
    else
    {
        pq->tail->next = newnode;
        pq->tail = newnode;
    }
     pq->size++;
}
 void QueuePop(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
     // 队列中只有一个节点
    if (pq->head->next == NULL)
    {
        free(pq->head);
        pq->head = pq->tail = NULL;
    }
    else
    {
        QNode* del = pq->head;
        pq->head = pq->head->next;
        free(del);
        //del = NULL;
    }
     pq->size--;
}
 QDataType QueueFront(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
     return pq->head->data;
}
 QDataType QueueBack(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
     return pq->tail->data;
}
 bool QueueEmpty(Queue* pq)
{
    assert(pq);
     return pq->size == 0;
    //return pq->head == NULL && pq->tail == NULL;
}
int QueueSize(Queue* pq)
{
    assert(pq);
     return pq->size;
}

初始化队列

头指针和尾指针都指向空,队列元素个数初始化为0

void QueueInit(Queue* pq)
{
    assert(pq);
    pq->head = pq->tail = NULL;
    pq->size = 0;
}

销毁队列

利用while循环将申请的节点一一释放掉,然后头指针pq->head和尾指针pq->tail指向空,栈的数据个数置为 0pq->size = 0

void QueueDestroy(Queue* pq)
{
    assert(pq);
     QNode* cur = pq->head;
    while (cur)
    {
        QNode* del = cur;
        cur = cur->next;
        free(del);
    }
     pq->head = pq->tail = NULL;
    pq->size = 0;
}

数据入队

1.申请新的节点newnode newnode->data = x,newnode->next = NULL

2.数据入队:当pq->tail == NULL时,队列中没有节点,那么头指针和尾指针都赋值为newnode pq->head = pq->tail = newnode;当pq->tail != NULL时,队列中有节点,那么尾部链接上新节点newnode,然后newnode成为新的尾结点。

3.队列数据个数加一pq->size++

void QueuePush(Queue* pq, QDataType x)
{
    assert(pq);
    QNode* newnode = (QNode*)malloc(sizeof(QNode));
    if (newnode == NULL)
    {
        perror("malloc fail");
        exit(-1);
    }
    else
    {
        newnode->data = x;
        newnode->next = NULL;
    }
     // 队列中没有节点
    if (pq->tail == NULL)
    {
        pq->head = pq->tail = newnode;
    }
    else
    {
        pq->tail->next = newnode;
        pq->tail = newnode;
    }
     pq->size++;
}

数据出队

1.判断队列是否为空

2.数据出队:当pq->head->next == NULL时,队列中只有一个节点,释放该节点,头指针和尾指针都指向空;当pq->head->next != NULL时,释放让头指针指向当前节点的下一个节点,释放原来的头节点

3.队列数据个数减一pq->size--

void QueuePop(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
     // 队列中只有一个节点
    if (pq->head->next == NULL)
    {
        free(pq->head);
        pq->head = pq->tail = NULL;
    }
    else
    {
        QNode* del = pq->head;
        pq->head = pq->head->next;
        free(del);
        //del = NULL;
    }
     pq->size--;
}

返回队头数据

先判断队列是否为空,不为空时,返回队头数据。

QDataType QueueFront(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
     return pq->head->data;
}

返回队尾数据

先判断队列是否为空,不为空时,返回队尾数据。

QDataType QueueFront(Queue* pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));
     return pq->tail->data;
}

判断队列是否为空

判断队列是否为空有两种方式:1.判断pq->size等不等于 0;2.判断头指针pq->head和尾指针pq->tail是否等于空指针NULL

bool QueueEmpty(Queue* pq)
{
    assert(pq);
     return pq->size == 0;
    //return pq->head == NULL && pq->tail == NULL;
}

队列中数据的个数

直接返回队列数据的个数pq->size

int QueueSize(Queue* pq)
{
    assert(pq);
     return pq->size;
}

Test.c

以下为测试函数接口的代码,大家可以参考一下。需要注意的是,打印队列中的数据是通过打印队头数据、Pop掉队头数据的方式来实现的。

#include "Queue.h"
 void QueueTest()
{
    Queue q;
    QueueInit(&q);
    QueuePush(&q, 1);
    QueuePush(&q, 2);
    QueuePush(&q, 3);
     printf("%d ", QueueFront(&q));
    QueuePop(&q);
    printf("%d ", QueueFront(&q));
    QueuePop(&q);
     QueuePush(&q, 4);
    QueuePush(&q, 5);
    QueuePush(&q, 6);
     while (!QueueEmpty(&q))
    {
        printf("%d ", QueueFront(&q));
        QueuePop(&q);
    }
    printf("\n");
     QueueDestroy(&q);
}
 int main()
{
    QueueTest();
     return 0;
}


c

相关推荐

PHP实现部分字符隐藏

沙雕mars · 1327浏览 · 2019-04-28 09:47:56
Java中ArrayList和LinkedList区别

kenrry1992 · 909浏览 · 2019-05-08 21:14:54
Tomcat 下载及安装配置

manongba · 974浏览 · 2019-05-13 21:03:56
JAVA变量介绍

manongba · 964浏览 · 2019-05-13 21:05:52
什么是SpringBoot

iamitnan · 1090浏览 · 2019-05-14 22:20:36
加载中

0评论

评论
我爱编程,我爱工作,更爱生活
小鸟云服务器
扫码进入手机网页