数据结构与算法学习笔记三---循环队列的表示和实现(C++)

目录

前言

1.为什么要使用循环队列

2.队列的顺序存储方式的实现

1.定义

2.队列初始化

3.销毁

4.清空队列

5.队列是否为空

6.队列长度

7.队头

8.入队

9.出队

10.遍历队列

11.完整代码

3.参考资料


前言

    这篇文章介绍循环队列的表示和用法

1.为什么要使用循环队列

        在上一篇文章中,我们知道了顺序的循环表示和实现方法。但是我们会发现当我们在操作顺序链表的时候,我们频繁的操作顺序队列,而队列又不为空的时候,出队列的一些存储空间会变得不可用。

        如下图所示,当我rear=3,front=2的时候,顺序队列中至少有连个存储空间空间是不可以使用的,这无疑会浪费一些存储空间。那么有没有办法让我们在出队列之后,重复利用之前存储空间呢,答案是有的。

        图1.顺序队列的出队列和入队列操作示意图

        这里借鉴了网上老师的三种解决方案:

        1.使用计数器记录队列中的元素个数

        2.加标志位,删除的时候标志位置1,插入置0,当front = rear并且标志位为0,表示队列为空,当front=rear并且标志位为1的时候,表示队列经满。

        3.认为浪费一个存储空间,改成一个循环队列来实现。

        这里下面代码的表示和实现采用的第三种方案。

        关于循环队列的理解,感觉严蔚敏老师的讲解还是不错的,直接贴个图吧。

图2.严蔚敏老师数据结构与算法中关于循环队列的思路

2.队列的顺序存储方式的实现

1.定义

struct CircularQueue {
    int *base;
    int front;
    int rear;
    int maxSize; // 队列的最大容量
};

2.队列初始化

// 队列初始化
Status initQueue(CircularQueue &circularQueue, int maxSize) {
    circularQueue.base = new int[maxSize]; // 为循环队列分配内存
    if (!circularQueue.base) {
        return 0; // 内存分配失败
    }
    circularQueue.front = circularQueue.rear = 0; // 初始化队首和队尾指针
    circularQueue.maxSize = maxSize;
    return 1; // 初始化成功
}

3.销毁

// 销毁队列
void destroyQueue(CircularQueue &circularQueue) {
    if (circularQueue.base) {
        delete[] circularQueue.base; // 释放内存
        circularQueue.base = nullptr; // 将指针置为空
    }
}

4.清空队列

// 清空队列
void clearQueue(CircularQueue &circularQueue) {
    circularQueue.front = circularQueue.rear = 0; // 重置队首和队尾指针
}

5.队列是否为空

// 判断队列是否为空
bool isEmptyQueue(CircularQueue &circularQueue) {
    return circularQueue.front == circularQueue.rear; // 当队首和队尾指针相同时,队列为空
}

6.队列长度

// 获取队列长度
int queueLength(CircularQueue &circularQueue) {
    return (circularQueue.rear - circularQueue.front + circularQueue.maxSize) % circularQueue.maxSize;
}

7.队头

// 获取队首元素
Status getQueueFront(CircularQueue &circularQueue, int &frontElement) {
    if (isEmptyQueue(circularQueue)) {
        return 0; // 队列为空
    }
    frontElement = circularQueue.base[circularQueue.front];
    return 1; // 成功获取队首元素
}

8.入队

// 入队
bool enQueue(CircularQueue &circularQueue, int element) {
    // 检查队列是否已满
    if ((circularQueue.rear + 1) % circularQueue.maxSize == circularQueue.front) {
        return false; // 队列已满
    }
    // 入队操作
    circularQueue.base[circularQueue.rear] = element;
    circularQueue.rear = (circularQueue.rear + 1) % circularQueue.maxSize; // 移动队尾指针
    return true; // 入队成功
}

9.出队

// 出队
bool deQueue(CircularQueue &circularQueue, int &element) {
    // 检查队列是否为空
    if (isEmptyQueue(circularQueue)) {
        return false; // 队列为空,无法出队
    }
    // 出队操作
    element = circularQueue.base[circularQueue.front];
    circularQueue.front = (circularQueue.front + 1) % circularQueue.maxSize; // 移动队首指针
    return true; // 出队成功
}

10.遍历队列

// 遍历队列
void traverseQueue(CircularQueue &circularQueue) {
    // 遍历队列并打印元素
    int i = circularQueue.front;
    while (i != circularQueue.rear) {
        cout << circularQueue.base[i] << " ";
        i = (i + 1) % circularQueue.maxSize;
    }
    cout << endl;
}

11.完整代码

#include <iostream>
using namespace std;

typedef int Status;

struct CircularQueue {
    int *base;
    int front;
    int rear;
    int maxSize; // 队列的最大容量
};

// 队列初始化
Status initQueue(CircularQueue &circularQueue, int maxSize) {
    circularQueue.base = new int[maxSize]; // 为循环队列分配内存
    if (!circularQueue.base) {
        return 0; // 内存分配失败
    }
    circularQueue.front = circularQueue.rear = 0; // 初始化队首和队尾指针
    circularQueue.maxSize = maxSize;
    return 1; // 初始化成功
}

// 销毁队列
void destroyQueue(CircularQueue &circularQueue) {
    if (circularQueue.base) {
        delete[] circularQueue.base; // 释放内存
        circularQueue.base = nullptr; // 将指针置为空
    }
}

// 清空队列
void clearQueue(CircularQueue &circularQueue) {
    circularQueue.front = circularQueue.rear = 0; // 重置队首和队尾指针
}

// 判断队列是否为空
bool isEmptyQueue(CircularQueue &circularQueue) {
    return circularQueue.front == circularQueue.rear; // 当队首和队尾指针相同时,队列为空
}

// 获取队列长度
int queueLength(CircularQueue &circularQueue) {
    return (circularQueue.rear - circularQueue.front + circularQueue.maxSize) % circularQueue.maxSize;
}

// 获取队首元素
Status getQueueFront(CircularQueue &circularQueue, int &frontElement) {
    if (isEmptyQueue(circularQueue)) {
        return 0; // 队列为空
    }
    frontElement = circularQueue.base[circularQueue.front];
    return 1; // 成功获取队首元素
}

// 入队
bool enQueue(CircularQueue &circularQueue, int element) {
    // 检查队列是否已满
    if ((circularQueue.rear + 1) % circularQueue.maxSize == circularQueue.front) {
        return false; // 队列已满
    }
    // 入队操作
    circularQueue.base[circularQueue.rear] = element;
    circularQueue.rear = (circularQueue.rear + 1) % circularQueue.maxSize; // 移动队尾指针
    return true; // 入队成功
}

// 出队
bool deQueue(CircularQueue &circularQueue, int &element) {
    // 检查队列是否为空
    if (isEmptyQueue(circularQueue)) {
        return false; // 队列为空,无法出队
    }
    // 出队操作
    element = circularQueue.base[circularQueue.front];
    circularQueue.front = (circularQueue.front + 1) % circularQueue.maxSize; // 移动队首指针
    return true; // 出队成功
}

// 遍历队列
void traverseQueue(CircularQueue &circularQueue) {
    // 遍历队列并打印元素
    int i = circularQueue.front;
    while (i != circularQueue.rear) {
        cout << circularQueue.base[i] << " ";
        i = (i + 1) % circularQueue.maxSize;
    }
    cout << endl;
}

int main() {
    CircularQueue circularQueue;
    int maxSize = 10; // 队列的最大容量
    initQueue(circularQueue, maxSize); // 初始化循环队列

    // 测试入队
    for (int i = 1; i <= 5; ++i) {
        enQueue(circularQueue, i * 10);
    }

    // 输出队列元素
    cout << "队列元素:";
    traverseQueue(circularQueue);

    // 获取队首元素
    int frontElement;
    if (getQueueFront(circularQueue, frontElement)) {
        cout << "队首元素:" << frontElement << endl;
    }

    // 测试出队
    int element;
    for (int i = 0; i < 3; ++i) {
        if (deQueue(circularQueue, element)) {
            cout << "出队元素:" << element << endl;
        }
    }

    // 输出队列元素
    cout << "队列元素:";
    traverseQueue(circularQueue);

    // 判断队列是否为空
    if (isEmptyQueue(circularQueue)) {
        cout << "队列为空" << endl;
    } else {
        cout << "队列不为空" << endl;
    }

    // 获取队列长度
    cout << "队列长度:" << queueLength(circularQueue) << endl;

    // 清空队列
    clearQueue(circularQueue);

    // 判断清空后队列是否为空
    if (isEmptyQueue(circularQueue)) {
        cout << "清空队列后,队列为空" << endl;
    } else {
        cout << "清空队列后,队列不为空" << endl;
    }

    // 销毁队列
    destroyQueue(circularQueue);

    return 0;
}

3.参考资料

1.B站上看到的一个老师的讲解

2.数据结构C语言版(1997年清华大学出版社出版的图书)_百度百科

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用curl命令查看服务器端口开放情况

目录 1.ssh端口 22 2.mysql数据库端口 3306 3.web应用端口 &#xff08;Jellyfin 8082&#xff09; &#xff08;wordpress 8088&#xff09; &#xff08;tomcat 8080&#xff09; 4.不存在的端口 5.被防火墙阻挡的端口 1.ssh端口 22 curl -v 10.10.10.205:22 curl…

嵌入式全栈开发学习笔记---C语言笔试复习大全16

目录 指针和数组 用指针来表示数组 用数组来表示指针 笔试题19 上一篇复习了指针使用时的相关注意事项&#xff0c;这一篇我们开始复习指针和数组。 说明&#xff1a;我们学过单片机的一般都是有C语言基础的了&#xff0c;网上关于C语言的资料有很多&#xff0c;大家如果对…

Modbus通讯协议初学

目录 Modbus通讯协议初学什么是Modbus?Modbus用来做什么?4个种类的寄存器协议速记功能码Modbus 报文帧示例解读 Modbus通讯协议初学 什么是Modbus? 顾名思义,它是一个bus,即总线协议。比如串口协议、IIC协议、SPI都是通讯协议。你接触到这种协议,相信你所处的行业是工业方…

第3周 后端微服务基础架构与前端项目联调配备

第3周 后端微服务基础架构与前端项目联调配备 1. 微服务项目层次设计与Maven聚合1.1 项目层次设计1.2 父项目pom1.2.1 打包方式 1.3 创建通用 ************************************************************************************** 1. 微服务项目层次设计与Maven聚合 1.1…

牛客NC404 最接近的K个元素【中等 二分查找+双指针 Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/b4d7edc45759453e9bc8ab71f0888e0f 知识点 二分查找&#xff1b;找到第一个大于等于x的数的位置idx;然后从idx开始往两边扩展Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、…

Spring Boot 调用外部接口的几种方式

Spring Boot 调用外部接口的几种方式 在微服务架构中&#xff0c;服务间的调用是不可或缺的环节。Spring Boot 为开发者提供了多种方式来实现这一任务&#xff0c;这个文章将为你详细介绍这些方式。 一、使用RestTemplate RestTemplate是 Spring Boot 早期版本中常用的 REST 客…

头歌C语言数据结构(队列的应用)

第1关&#xff1a;循环队列 任务描述 本关任务&#xff1a;编写一个循环队列&#xff0c;实现入队、出队操作&#xff0c;判断队空、队满等特殊情况。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.循环队列定义&#xff0c;2.入队、出队的定义&#xff…

Vue3路由及登录注销功能、设置导航守护功能模块

路由 在vue中&#xff0c;页面和组件都是.vue文件&#xff0c;可以说是一样的&#xff0c;结构、内容和生产方法都是一样&#xff0c;但是组件可以被反复使用&#xff0c;但页面一般只被使用一次。 路由的作用就是网页地址发生变化时&#xff0c;在App.vue页面的指定位置可以加…

【数据结构】双向循环链表专题解析

实现自己既定的目标&#xff0c;必须能耐得住寂寞单干。&#x1f493;&#x1f493;&#x1f493; 目录 •✨说在前面 &#x1f34b;知识点一&#xff1a;双向链表的结构 • &#x1f330;1."哨兵位"节点 • &#x1f330;2.双向带头循环链表的结构 &#x1f34b;…

[C#] 使用HttpClient请求https地址报错的解决方案

当使用HttpClient请求HTTPS地址遇到报错时&#xff0c;下面将解析并提供可能的解决方案供参考。 文章目录 异常代码无法定位错误的准确定位错误的 常见错误错误1错误2 解决问题生产环境开发环境 异常代码 首先&#xff0c;需要查看引发异常的代码部分, 无法定位错误的 以下代…

《完美黑暗》重启版6月发布,分析指出开发“没有问题” 状况没那么

易采游戏网5月12日消息&#xff0c;在21世纪初的游戏界&#xff0c;一款名为《完美黑暗》的FPS游戏在N64平台上崭露头角&#xff0c;以其独特的剧情设定和丰富的武器系统赢得了众多玩家的喜爱。然而&#xff0c;这款作品在推出时也并非一帆风顺&#xff0c;受到了不少玩家的吐槽…

C++ | Leetcode C++题解之第77题组合

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> temp;vector<vector<int>> ans;vector<vector<int>> combine(int n, int k) {// 初始化// 将 temp 中 [0, k - 1] 每个位置 i 设置为 i 1&#xff0c;即 [0, k - 1] 存…

springcloud整合网关(springcloud-gateway) 跨域处理

pom引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- 服务注册 --><dependency><groupId>com.alibaba.cloud</groupId&…

使用Pandas对Data列进行基于顺序的分组排列

目录 一、引言 二、Pandas库简介 三、按照数据列中元素出现的先后顺序进行分组排列 四、案例分析 五、技术细节探讨与扩展应用 1. 技术细节 2. 扩展应用 3. 示例代码&#xff1a;用户行为分析 4. 进阶应用&#xff1a;分组后的聚合操作 5. 分组后的数据筛选 6. 分组…

【算法】滑动窗口——找到字符串中所有字母异位词

本节博客是对题目——找到字符串中所有字母异位词的从读题到代码实现以及优化的详细解读&#xff0c;有需要借鉴即可。 目录 1.题目2.滑动窗口 哈希数组3.异位词优化4.总结 1.题目 题目链接&#xff1a;LINK 首先来解释一下什么是异位词&#xff0c;所谓“异位词”&#xf…

JavaWeb文件上传/下载(Servlet)

效果 文件下载 文件上传 项目概述 Jakarta EE9&#xff0c;Web项目 项目文件结构 0 maven依赖&#xff0c;资源文件 <!-- lombok插件--> <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId&g…

最新的云渲染100活动有哪些?渲染100邀请码1a12

随着科技的进步&#xff0c;云渲染已经成为设计行业的必备工具&#xff0c;各个云渲染平台为了吸引用户也推出各种各样的活动&#xff0c;今天我们以广受好评的渲染100为例&#xff0c;来说下它们的活动体系。 1、新用户活动 渲染100对新用户很友好&#xff0c;提供了充足的测…

欢乐钓鱼大师攻略,怎么获取道具?

在《欢乐钓鱼大师》的游戏世界中&#xff0c;道具是提升钓鱼体验、解锁新功能以及完成挑战的关键。通过多种方式获取道具&#xff0c;能够帮助玩家更好地探索游戏世界、挑战自我&#xff0c;以及与其他玩家展开竞争。以下是关于如何获取道具的详细攻略&#xff0c;让你能够在游…

AI写作推荐-写文ai-AI在线写作生成器-3步完成写作任务

AI写作利器&#xff1a;推荐几款神助攻文案创作工具 随着技术的进步&#xff0c;人工智能&#xff08;AI&#xff09;已达到高级水平&#xff0c;在众多领域展现其强大能力。 在文本创作的领域&#xff0c;人工智能&#xff08;AI&#xff09;应用已显著地提升了写作效率和创意…

Java后端实现对象与文件接收数据(minio测试)

实现思路&#xff1a; 1. 两个接口实现&#xff0c;一个接对象数据(file)&#xff0c;一个接文件数据(json)。 2. json对象(base64String) 实体类信息 &#xff0c;请求体统一接收 3. file, String name ,String password ,String name &#xff0c; Controller层接收 统一…