九、数据结构——顺序队列中的循环队列

news2024/12/26 22:16:52

目录

一、循环队列的定义
二、循环队列的实现
三、循环队列的基本操作

  • ①初始化
    ②判空
    ③判满
    ④入队
    ⑤出队
    ⑥获取长度
    ⑦打印

四、循环队列的应用
五、全部代码

数据结构中的循环队列

在数据结构中,队列(Queue)是一种常见的线性数据结构,遵循先进先出(First In First Out,FIFO)的原则。循环队列是队列的一种变体,它可以更高效地利用存储空间,并解决了普通队列可能出现的假溢出问题。本篇博客将详细介绍循环队列的定义、实现和基本操作。
在这里插入图片描述

一、 循环队列的定义

循环队列是通过数组或链表实现的一种队列,它将队列的首尾相连,形成一个循环。在循环队列中,队尾指针(rear)可能在队列的前面,队头指针(front)可能在队列的后面。当队列为空时,front和rear指向同一个位置。当队列满时,front和rear之间有一个空位。

二、循环队列的实现

我们可以通过数组来实现循环队列。为了更好地利用存储空间,通常会预留一个位置来区分队列是空还是满。具体来说,我们需要定义一个固定大小的数组和两个指针front和rear来表示队头和队尾。

typedef int TypeData;
typedef struct Node{
    TypeData *data;
    int front;
    int rear;
    int len;
}Queue,*Pqueue;

三、循环队列的基本操作

①初始化队列

Pqueue init_queue(Pqueue *queue, int m){
    *queue = (Pqueue)malloc(sizeof(Queue));
    if(*queue == NULL){
        return NULL;
    }
    (*queue)->data = (TypeData *)malloc(sizeof(Queue) * m);
    (*queue)->front = (*queue)->rear= 0;
    (*queue)->len = m;
    return *queue;
}

②判空

int isEmpty(Pqueue queue){
    return queue->front == queue->rear;
}

③判满

int full(Pqueue queue){
    return (queue->rear+1) % (queue->len) == (queue->front);
}

④入队

int queue_en(Pqueue queue, TypeData value){
    if(full(queue)){
        return -1;
    }
    queue->data[queue->rear] = value;
    queue->rear = (queue->rear+ 1) % (queue->len);
    return 0;
}

⑤出队

TypeData queue_de(Pqueue queue){
    if(isEmpty(queue)){
        return -1;
    }
    TypeData temp = queue->data[queue->front];
    queue->front = (queue->front + 1) % (queue->len);
    return temp;
}

⑥获取队列长度

int get_length(Pqueue queue){
#if 0
    int a = queue->rear - queue->front;
    if(a >= 0){
        return a;
    }else{
        return (a + queue->len) % (queue->len);
    }
#else 
    return (queue->rear - queue->front + queue->len) % queue->len;
#endif
}

⑦打印

void show(Pqueue queue){
    for(int i = queue->front; i != queue->rear; i = (i + 1) % queue->len){
        printf("%d ",queue->data[i]);
    }
    printf("\n");
}

四、循环队列的应用

循环队列常用于解决生产者-消费者问题,以及在需要定期缓存数据时。它还在计算机操作系统的进程调度中得到广泛应用,用于管理就绪队列。循环队列的高效性和简单性使其成为许多问题的理想解决方案。

五、全部代码

①seqqueue.h

#ifndef _SEQQUEUE_H_
#define _SEQQUEUE_H_
#include <stdio.h>
#include <stdlib.h>

typedef int TypeData;
typedef struct Node{
    TypeData *data;
    int front;
    int tail;
    int len;
}Queue,*Pqueue;

Pqueue init_queue(Pqueue *queue, int m);

int isEmpty(Pqueue queue);

int full(Pqueue queue);

int get_length(Pqueue queue);

int queue_en(Pqueue queue, TypeData value);

TypeData queue_de(Pqueue queue);

void show(Pqueue queue);

#endif

②seqqueue.c

#include "seqqueue.h"
Pqueue init_queue(Pqueue *queue, int m){
    *queue = (Pqueue)malloc(sizeof(Queue));
    if(*queue == NULL){
        return NULL;
    }
    (*queue)->data = (TypeData *)malloc(sizeof(Queue) * m);
    (*queue)->front = (*queue)->tail = 0;
    (*queue)->len = m;
    return *queue;
}

int isEmpty(Pqueue queue){
    return queue->front == queue->tail;
}

int full(Pqueue queue){
    return (queue->tail+1) % (queue->len) == (queue->front);
}

int get_length(Pqueue queue){
#if 0
    int a = queue->tail - queue->front;
    if(a >= 0){
        return a;
    }else{
        return (a + queue->len) % (queue->len);
    }
#else 
    return (queue->tail - queue->front + queue->len) % queue->len;
#endif
}

int queue_en(Pqueue queue, TypeData value){
    if(full(queue)){
        return -1;
    }
    queue->data[queue->tail] = value;
    queue->tail = (queue->tail + 1) % (queue->len);
    return 0;
}

TypeData queue_de(Pqueue queue){
    if(isEmpty(queue)){
        return -1;
    }
    TypeData temp = queue->data[queue->front];
    queue->front = (queue->front + 1) % (queue->len);
    return temp;
}

void show(Pqueue queue){
    for(int i = queue->front; i != queue->tail; i = (i + 1) % queue->len){
        printf("%d ",queue->data[i]);
    }
    printf("\n");
}

③seqqueue_main.c

#include "seqqueue.h"
#include "seqqueue.c"
#include <unistd.h>
int main(int argc, char *argv[])
{ 
    Pqueue queue;
    init_queue(&queue, 10);

    printf("入队:");
    queue_en(queue, 20);
    queue_en(queue, 55);
    queue_en(queue, 60);
    queue_en(queue, 99);
    queue_en(queue, 22);
    queue_en(queue, 66);
    queue_en(queue, 100);
    show(queue);
    
    printf("出队:");
    queue_de(queue);

    show(queue);
    
    printf("队内还有%d个元素",get_length(queue));
    printf("\n");

    return 0;
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/784182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

防火墙NAT地址转换的四种应用实验与防火墙的双机热备实验

一、NAT实验 一、源地址转换 1、首先搭建NAT实验环境的拓扑&#xff1a; 这里需要配置各个设备的ip、掩码、网关&#xff1b;省略 2、登录防火墙设备并且为防火墙设备的0/0/0接口配置与虚拟网卡一个网段的ip&#xff0c;并且开启该接口的全部服务 [USG6000V1]int gi 0/0/0…

Keil系列教程11_工程窗口图标说明

1写在前面 很多朋友看到如下工程窗口的图标&#xff08;如&#xff1a;带有“叹号”、“星号”、“钥匙”、“禁止驶入”标志&#xff09;&#xff0c;就会产生疑问&#xff1a;这些图标到底是啥意思呢&#xff1f; 其实&#xff0c;这些不同标志的图标是代表着不同的含义&…

AWVS 15.6 使用教程

目录 介绍 版本 AWVS具有以下特点和功能&#xff1a; 功能介绍&#xff1a; Dashboard功能&#xff1a; Targets功能&#xff1a; Scans功能&#xff1a; Vulnerabilities功能&#xff1a; Reports功能&#xff1a; Users功能&#xff1a; Scan Profiles功能&#x…

MyBatis查询数据库(2)

目录 前言&#x1f36d; 一、增删查改操作 1、查 Ⅰ、mapper接口&#xff1a; Ⅱ、UserMapper.xml 查询所有用户的具体实现 SQL&#xff1a; Ⅲ、进行单元测试 2、增、删、改操作 Ⅰ、增 添加用户 添加用户并且返回自增 id Ⅱ、改 根据id修改用户名 开启 MyBatis …

leetcode每日一练-第141题-环形链表

一、思路 双指针 二、解题方法 使用了正确的快慢环指针方法来判断链表。快指针每次向前移动两步&#xff0c;慢指针每次移动一步&#xff0c;如果链表中向前移动一步&#xff0c;它们最终会相遇。如果链表不存在环&#xff0c;快指针会先到达链表是否存在&#xff0c;此时存在…

【C#】using

文章目录 global 修饰符using 别名结合“global 修饰符”和“using 别名”static 修饰符来源 global 修饰符 向 using 指令添加 global 修饰符意味着 using 将应用于编译中的所有文件&#xff08;通常是一个项目&#xff09;。 global using 指令被添加到 C# 10 中。 其语法为…

怎么快速定位bug?怎么编写测试用例?

目录 01定位问题的重要性 02问题定位技巧 03初次怎么写用例 作为一名测试人员如果连常见的系统问题都不知道如何分析&#xff0c;频繁将前端人员问题指派给后端人员&#xff0c;后端人员问题指派给前端人员&#xff0c;那么在团队里你在开发中的地位显而易见 &#xff0c;口碑…

什么?按Home键SingleInstance Activity销毁了???

前段时间&#xff0c;突然有朋友询问&#xff0c;自己写的SingleInstance Activity在按home键的时候被销毁了&#xff0c;刚听到这个问题的时候&#xff0c;我直觉怀疑是Activity在onPause或者onStop中发生了Crash导致闪退了&#xff0c;但是安装apk查看现象&#xff0c;没有发…

摸索graphQL在前端vue中使用过程(四)

请求网址https://hasura.io/learn/graphql&#xff0c;他这个Authorization好像每天就会一次变化&#xff0c;需要注意。 之前用到了一种类型ID&#xff0c;也就是说&#xff0c;在GraphQL的查询标量的过程中。 标量:就是被查询的字段名称。 这里再补充一点知识&#xff0c;统…

Android 包体积资源优化实践

1 插件优化 插件优化资源在得物App最新版本上收益12MB。插件优化的日志在包体积平台有具体的展示&#xff0c;也是为了提供一个资源问题追溯的能力。 1.1 插件环境配置 插件首先会初始化环境配置&#xff0c;如果机器上未安装运行环境则会去oss下载对应的可执行文件。 1.2 图…

Windows 在VMware16.x安装Win11系统详细教程

文章目录 一、准备二、创建虚拟机1. 创建新的虚拟机2. 选择虚拟机硬件兼容性3. 安装客户机操作系统4. 选择客户机操作系统5. 命名虚拟机6. 固件类型7. 处理器配置8. 此虚拟机内存9. 网络类型10. 选择I/O控制器类型11. 选择磁盘类型12. 选择磁盘13. 指定磁盘容量14. 指定磁盘文件…

【深度学习】日常笔记15

训练集和测试集并不来⾃同⼀个分布。这就是所谓的分布偏移。 真实⻛险是从真实分布中抽取的所有数据的总体损失的预期&#xff0c;然⽽&#xff0c;这个数据总体通常是⽆法获得的。计算真实风险公式如下&#xff1a; 为概率密度函数 经验⻛险是训练数据的平均损失&#xff0c;⽤…

python机器学习(四)线性代数回顾、多元线性回归、多项式回归、标准方程法求解、线性回归案例

回顾线性代数 矩阵 矩阵可以理解为二维数组的另一种表现形式。A矩阵为三行两列的矩阵&#xff0c;B矩阵为两行三列的矩阵&#xff0c;可以通过下标来获取矩阵的元素&#xff0c;下标默认都是从0开始的。 A i j : A_{ij}: Aij​:表示第 i i i行&#xff0c;第 j j j列的元素。…

N位分频器的实现

N位分频器的实现 一、 目的 使用verilog实现n位的分频器&#xff0c;可以是偶数&#xff0c;也可以是奇数 二、 原理 FPGA中n位分频器的工作原理可以简要概括为: 分频器的作用是将输入时钟频率分频,输出低于输入时钟频率的时钟信号。n位分频器可以将输入时钟频率分频2^n倍…

linux进阶-I.MX 6ULL

目录 启动模式&#xff08;8引脚设置启动模式&#xff09; 对应原理图 boot ROM程序 空偏移 映像向量表&#xff08;Image vector table&#xff0c;IVT&#xff09; IVT结构体 Boot data DCD&#xff08;外设寄存器配置信息&#xff0c;初始化关键外设&#xff09; NXP…

如何使用 After Effects 导出摄像机跟踪数据到 3ds Max

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 在本教程中&#xff0c;我将展示如何在After Effects中跟踪实景场景&#xff0c;然后将相机数据导出到3ds Max。 1. 项目设置 步骤 1 打开“后效”。 打开后效果 步骤 2 转到合成>新合成以创建新合…

Docker Compose(九)

一、背景&#xff1a; 对于现代应用来说&#xff0c;大多数都是通过很多的微服务互相协同组成一个完整的应用。例如&#xff0c;订单管理、用户管理、品类管理、缓存服务、数据库服务等&#xff0c;他们构成了一个电商平台的应用。而部署和管理大量的服务容器是一件非常繁琐的事…

【图像处理】使用自动编码器进行图像降噪(改进版)

阿里雷扎凯沙瓦尔兹 一、说明 自动编码器是一种学习压缩和重建输入数据的神经网络。它由一个将数据压缩为低维表示的编码器和一个从压缩表示中重建原始数据的解码器组成。该模型使用无监督学习进行训练&#xff0c;旨在最小化输入和重建输出之间的差异。自动编码器可用于降维、…

宋浩线性代数笔记(二)矩阵及其性质

更新线性代数第二章——矩阵&#xff0c;本章为线代学科最核心的一章&#xff0c;知识点多而杂碎&#xff0c;务必仔细学习。 重难点在于&#xff1a; 1.矩阵的乘法运算 2.逆矩阵、伴随矩阵的求解 3.矩阵的初等变换 4.矩阵的秩 &#xff08;去年写的字&#xff0c;属实有点ugl…