顺序队列的实现及其应用

一、概念

  • 队列是允许在两端(队头、队尾)进行插入和读出操作线性表

  • 默认情况下队尾插入,队头读出 (这一点和排队很像),先进先出FIFO

  • 队中没有元素时称为空队

  • 当队列两端都允许插入、读出 时,称为双端队列

二、顺序队列的结构模型

cpp 复制代码
typedef int data_t

#define N (128)	//队列容量
    
typedef struct{
    data_t data[N]; //数组作为队列的存储空间
    int front; //队头 指向队头元素
    int rear;  //队尾 指向队尾元素的下一个位置
}sequeue;

2.1队空

刚创建的空队列就是如此,由此也可以得到空队的条件就是:front == rear

2.2入队

假设入队D1、D2、D3

这里入队的逻辑是,先入队元素,rear再移动(实际上也是rear++)

特殊情况是:入队的元素过多导致rear溢出,可以利用取余操作来避免这一风险

即:rear = (rear+1) % N

因此,这样一来也促成了**"循环队列"**

2.3出队

依次出队D1、D2

这里出队的逻辑是:先出队元素,front再移动

这里出队实际上也会遇到溢出情况,因为是循环队列,所以front的移动也对N取余即可

2.4满队

当队列再入队D7时,rear会移动到和front相同位置,但此刻是"满队",会和"空队"冲突

为了避免这个情况,D7不允许入队,解决办法是:入队时进行判断,如果rear+1等于front,那么不执行入队操作

三、顺序队列的实现

cpp 复制代码
typedef int data_t;
#define N 128

typedef struct{
    data_t data[N]; //数组作为队列的存储空间
    int front; //队头 指向队头元素
    int rear;  //队尾 指向队尾元素的下一个位置
}sequeue;

sequeue *queue_create(void);            //创建队列
int enqueue(sequeue *q, data_t value);  //入队
data_t dequeue(sequeue *q);             //出队
int queue_is_empty(sequeue *q);         //判断队列是否为空
int queue_is_full(sequeue *q);          //判断队列是否已满
int queue_clear(sequeue *q);            //清空队列
sequeue *queue_free(sequeue *q);        //释放队列空间

3.1创建

cpp 复制代码
sequeue *queue_create(void)
{
    sequeue *q;

    //申请空间
    q = (sequeue*)malloc(sizeof(sequeue));
    if(q == NULL)
    {
        printf("queue_create:malloc space failed!\n");
        return NULL;
    }
    //初始化
    memset(q->data,0,sizeof(q->data));
    q->front = 0;
    q->rear = 0;

    return q;
} 

3.2入队

cpp 复制代码
int enqueue(sequeue *q, data_t value)
{
    //参数检查
    if(q == NULL)
    {
        printf("enqueue:queue passed is NULL!\n");
        return -1;
    }
    //判断队列是否已满
     if( (( q->rear + 1) % N) == q->front)
    {
        printf("enqueue:queue is full!\n");
        return -1;
    }
    //入队
    q->data[q->rear] = value;
    //队尾++ 对N取余保证不溢出
    q->rear = (q->rear + 1) % N;

    return 1;
}

3.3出队

cpp 复制代码
data_t dequeue(sequeue *q) 
{
    data_t ret;//保存出队元素

    //参数检查
    if(q == NULL)
    {
        printf("dequeue:queue passed is NULL!\n");
        return -1;
    }

    //应由程序判断队列是否为空,这里就不判断了
    ret = q->data[q->front];
    //front移动
    q->front = (q->front + 1) % N;

    return ret;
}

3.4判断队列是否为空

cpp 复制代码
int queue_is_empty(sequeue *q)   
{
    //参数检查
    if(q == NULL)
    {
        printf("queue_is_empty:queue passed is NULL!\n");
        return -1;
    }

    return (q->front==q->rear? 1 : 0);
}

3.5判断队列是否已满

cpp 复制代码
int queue_is_full(sequeue *q)    
{
    //参数检查
    if(q == NULL)
    {
        printf("queue_is_full:queue passed is NULL!\n");
        return -1;
    }    

    //判断队列是否已满
    if( (( q->rear + 1) % N) == q->front)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

3.6清空队列

cpp 复制代码
int queue_clear(sequeue *q)       
{
    //参数检查
    if(q == NULL)
    {
        printf("queue_clear:queue passed is NULL!\n");
        return -1;
    }

    q->front = 0;
    q->rear = 0;

    return 1;
}

3.7释放队列空间

cpp 复制代码
sequeue *queue_free(sequeue *q)    
{
    //参数检查
    if(q == NULL)
    {
        printf("queue_free:queue passed is NULL!\n");
        return NULL;
    }

    free(q);
    q = NULL;

    return NULL;//传回主程序,避免野指针
}

四、应用

cpp 复制代码
#include <stdio.h>
#include "sequeue.h"

int main(void)
{
        sequeue *q;

        q = queue_create();
        if(q == NULL)
        {
                printf("queue_create:create failed!\n");
                return -1;
        }

        enqueue(q,10);
        enqueue(q,20);
        enqueue(q,30);
        enqueue(q,40);
        enqueue(q,50);
        enqueue(q,60);

        while(!queue_is_empty(q))
        {
                printf("dequeue:%d\n",dequeue(q));
        }

        q = queue_free(q);

        return 0;
}
相关推荐
02苏_5 分钟前
2025/1/21 学习Vue的第四天
学习
羊小猪~~28 分钟前
MYSQL学习笔记(四):多表关系、多表查询(交叉连接、内连接、外连接、自连接)、七种JSONS、集合
数据库·笔记·后端·sql·学习·mysql·考研
约定Da于配置30 分钟前
uniapp封装websocket
前端·javascript·vue.js·websocket·网络协议·学习·uni-app
milk_yan2 小时前
Docker集成onlyoffice实现预览功能
前端·笔记·docker
东京老树根2 小时前
Excel 技巧15 - 在Excel中抠图头像,换背景色(★★)
笔记·学习·excel
Ronin-Lotus3 小时前
嵌入式硬件篇---ADC模拟-数字转换
笔记·stm32·单片机·嵌入式硬件·学习·低代码·模块测试
编程小猹3 小时前
学习golang语言时遇到的难点语法
学习·golang·xcode
promising-w4 小时前
单片机基础模块学习——数码管
单片机·嵌入式硬件·学习
不爱学英文的码字机器4 小时前
我的2024:创作历程与成长总结
学习·程序人生·交友
UQI-LIUWJ4 小时前
LLM笔记:LayerNorm VS RMSNorm
笔记