数组实现循环队列

article/2025/9/22 21:08:14

循环队列
在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进:无论插入或删除,一旦rear指针增1或front指针增1 时超出了所分配的队列空间,就让它指向这片连续空间的起始位置。可以解决假溢出问题。从MaxSize-1增1变到0,可用取余运算rear%MaxSize和front%MaxSize来实现。这实际上是把队列空间想象成一个环形空间,环形空间中的存储单元循环使用,用这种方法管理的队列也就称为循环队列。除了一些简单应用之外,真正实用的队列是循环队列。

顺序队列的假溢出:当元素被插入到数组中下标最大的位置上之后,队列的空间就用尽了,但此时数组的低端还有空闲空间,这种现象叫做假溢出。
在这里插入图片描述

在循环队列中,当队列为空时,有front=rear,而当所有队列空间全占满时,也有front=rear。为了区别这两种情况,规定循环队列最多只能有MaxSize-1个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。因此,队列判空的条件时front=rear,而队列判满的条件时front=(rear+1)%MaxSize。队空和队满的情况如图:

在这里插入图片描述

在这里插入图片描述
循环队列的操作过程图:
在这里插入图片描述

循环队列的思路

  1. front 变量的含义: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
    front 的初始值 = 0
  2. rear 变量的含义:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
    rear 的初始值 = 0
  3. 当队列满时,条件是 (rear + 1) % maxSize == front 【满】
  4. 对队列为空的条件, rear == front 空
  5. 当我们这样分析, 队列中有效的数据的个数 (rear + maxSize - front) % maxSize // rear = 1 front = 0

实现的方法:
isEmpty()【判断队列是否为空】
isFull()【判断队列是否为满】
size()【获取队列当前有效元素个数】
addQueue()【向队列中添加元素】
getQueue()【获取队列的数据, 出队列】
headQueue()【显示队列的头数据, 注意不是取出数据】
showQueue()【展示队列所有元素】

代码实现如下:


import java.util.Scanner;/*** @anthor longzx* @create 2021 01 22 21:24* @Description**/
public class CircleArrayQueue {public static void main(String[] args) {//测试一把System.out.println("测试数组模拟环形队列的案例~~~");// 创建一个环形队列CircleArray queue = new CircleArray(4); //说明设置4, 其队列的有效数据最大是3char key = ' '; // 接收用户输入Scanner scanner = new Scanner(System.in);//boolean loop = true;// 输出一个菜单while (loop) {System.out.println("s(show): 显示队列");System.out.println("e(exit): 退出程序");System.out.println("a(add): 添加数据到队列");System.out.println("g(get): 从队列取出数据");System.out.println("h(head): 查看队列头的数据");key = scanner.next().charAt(0);// 接收一个字符switch (key) {case 's':queue.showQueue();break;case 'a':System.out.println("输出一个数");int value = scanner.nextInt();queue.addQueue(value);break;case 'g': // 取出数据try {int res = queue.getQueue();System.out.printf("取出的数据是%d\n", res);} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());}break;case 'h': // 查看队列头的数据try {int res = queue.headQueue();System.out.printf("队列头的数据是%d\n", res);} catch (Exception e) {// TODO: handle exceptionSystem.out.println(e.getMessage());}break;case 'e': // 退出scanner.close();loop = false;break;default:break;}}System.out.println("程序退出~~");}}class CircleArray {private int maxSize; // 表示数组的最大容量//front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素//front 的初始值 = 0private int front;//rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.//rear 的初始值 = 0private int rear; // 队列尾private int[] arr; // 该数据用于存放数据, 模拟队列public CircleArray(int arrMaxSize) {maxSize = arrMaxSize;arr = new int[maxSize];}// 判断队列是否满public boolean isFull() {return (rear  + 1) % maxSize == front;}// 判断队列是否为空public boolean isEmpty() {return rear == front;}// 添加数据到队列public void addQueue(int n) {// 判断队列是否满if (isFull()) {System.out.println("队列满,不能加入数据~");return;}//直接将数据加入arr[rear] = n;//将 rear 后移, 这里必须考虑取模rear = (rear + 1) % maxSize;}// 获取队列的数据, 出队列public int getQueue() {// 判断队列是否空if (isEmpty()) {// 通过抛出异常throw new RuntimeException("队列空,不能取数据");}// 这里需要分析出 front是指向队列的第一个元素// 1. 先把 front 对应的值保留到一个临时变量// 2. 将 front 后移, 考虑取模// 3. 将临时保存的变量返回int value = arr[front];front = (front + 1) % maxSize;return value;}// 显示队列的所有数据public void showQueue() {// 遍历if (isEmpty()) {System.out.println("队列空的,没有数据~~");return;}// 思路:从front开始遍历,遍历多少个元素// 动脑筋for (int i = front; i < front + size() ; i++) {System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);}}// 求出当前队列有效数据的个数public int size() {// rear = 2// front = 1// maxSize = 3return (rear + maxSize - front) % maxSize;}// 显示队列的头数据, 注意不是取出数据public int headQueue() {// 判断if (isEmpty()) {throw new RuntimeException("队列空的,没有数据~~");}return arr[front];}
}

http://chatgpt.dhexx.cn/article/3QatJW2b.shtml

相关文章

竞赛:图解循环数组--借助循环数组进行队列的模拟实现以及循环数组的理解讲解

文章目录 队列的模拟实现队列是什么实现过程实现原理具体代码实现 循环数组循环数组是什么&#xff1f;循环数组如何实现队列&#xff1f;实现原理 总结 队列的模拟实现 队列是什么 队列是一种数据结构&#xff0c;遵循的是先进先出&#xff0c;后进后出的原则&#xff0c;基…

循环数组、对象的方法(超实用)

&#xff08;前言&#xff1a;每一个方法我都会举例说明&#xff0c;为了避免混淆&#xff0c;所有方法例子中都使用同一个数组arr和对象obj&#xff1b;另外&#xff0c;由于 forEach太low&#xff0c;every太不常用&#xff0c;所以直接略过&#xff09; 1. for in &#x…

循环数组 及 实现

数组 是一种 线性结构&#xff0c; 在内存中是一段 连续的内存 存储空间存储。 那么 如何实现循环的数组呢&#xff1f; 什么是循环数组&#xff1f; 循环数组 就是 数组的头尾是相连的。 假如有一个数组 [3,7,2,9,1,5] , 形成的环形数组 如下图&#xff1a; 用代码实现&am…

js数组转换为数组对象

let arr ["刘备","关羽","张飞","赵云","马超","黄忠"]; let obj {}; // 将数组转化为对象 for (let key in arr) {obj[key] arr[key];}; let newObj Object.keys(obj).map(val > ({label: obj[val],value…

js 数组转对象方法

记录将数组转成对象方法 let array [1,2,3,4,5]; let obj {}; obj Object.assign({}, array) console.log(obj); // {1,2,3,4,5}

js数组添加对象

一般业务都会有在数组里添加对象属性的需求 以下列出几种常见的添加对象的方法供大家参考 一、最常见的方法&#xff1a;push&#xff08;尾部添加&#xff09; 业务场景 arr [{num:1},{num:2},{num:3}];newArr arr.push({num:4})console.log(arr) 结果&#xff1a; 二、…

js 多维数组/对象转一维数组对象

多维对象转数组&#xff1a; let objTree {name: 河南,children: {name: 洛阳,children: {name: 洛宁,children: {name: 兴华,},},},}function toList(obj, listre) {for (let key in obj) {if (typeof obj[key] object) {console.log(是对象, obj[key])toList(obj[key], li…

jQuery数组对象转javascript数组

当我们在前端开发中&#xff0c;使用了jQuery时&#xff0c;我们通常通过$(".box-item")的方式获取的是一个jQuery对象是一个类数组对象&#xff0c;当我们需要向后台传输的数据中&#xff0c;使用的是javascript数组&#xff0c;或者有时候&#xff0c;我们需要将jQ…

js 三维数组转对象数组 二维数组转对象数组

1. 三维数组转对象数组 输出&#xff1a; 代码如下&#xff1a; let dataArr [[[109.654541015625, 29.34387539941801],[110.467529296875, 59.34387539941801],[109.654541015625, 30.050076521698735],],]let list []dataArr[0].forEach(item > {let obj {lon: item[0…

如何在 JavaScript 中将数组转为对象

首先&#xff0c;我们需要明白对象具有键和值。 const object {key: value } 如果我们想把某个东西转换成一个对象&#xff0c;我们需要传递具有这两个要求的东西&#xff1a;键和值。 满足这些要求的参数有两种类型&#xff1a; 具有嵌套键值对的数组 Map 对象 数组 这是一个…

第二类斯特林数

概要&#xff1a; 第二类斯特林数表示将n个不同的元素分成m个集合的方案数。 代码 s[i][j]实现代码&#xff1a; const int mod1e97;//取模 LL s[N][N];//存放要求的第一类Stirling数 void init(){memset(s,0,sizeof(s));s[1][1]1;for(int i2;i<N-1;i){for(int j1;j<…

斯特林数

斯特林数分为第一类斯特林数和第二类斯特林数&#xff0c;第一类斯特林数分为有符号斯特林数和无符号斯特林数&#xff1b; 1.什么是圆排列&#xff1f; 圆排列是把n个数中拿出k个数组成一个圆的种类数&#xff0c;则这里组成m个圆排列的意思是组成m个不同的圆的种类数&…

斯特林数(Stirling)

第一类斯特林数 第一类斯特林数表示的是将n个不同元素分成k个不同的环的方案数。两个环不相同当且仅当这两个环不能通过旋转得到。记作s(n,k). s(n,k)的递推公式&#xff1a; s(n,k)(n-1)*s(n-1,k)s(n-1,k-1) ,1<k<n 边界条件&#xff1a;s(n,0)0 ,n>1 s(n,n)1 ,n…

斯特林数(Siteling_Number)

一、基本概念 斯特林数出现在许多组合枚举问题中. 第一类斯特林数 StirlingS1[n,m]&#xff0c; 给出恰包含 m 个圈的 n 个元素 的排列数目. 斯特林数满足母函数关系 . 注意某些 的定义与 Mathematica 中的不同&#xff0c;差别在于因子 . 第二类斯特林数 StirlingS2[n,m]给…

斯特林数(数论)

斯特林数&#xff1a;stirling 概念&#xff1a; 1、第一类斯特林数&#xff1a;把1~n排列成k个非空循环的方案数&#xff0c;用小写s(n,k)或[n k]表示 2、第二类斯特林数&#xff1a;将1~n排成k个非空集合的方案数&#xff0c;用大写S(n,k)或{n,k}表示 第一类斯特林数&…

组合数学 —— 斯特林数(Stirling)

【第一类斯特林数】 1.定理 第一类斯特林数 S1(n,m) 表示的是将 n 个不同元素构成 m 个圆排列的数目。 2.递推式 设人被标上1,2,.....p&#xff0c;则将这 p 个人排成 m 个圆有两种情况&#xff1a; 在一个圆圈里只有标号为 p 的人自己&#xff0c;排法有 S1(n-1,m-1) 个。…

Linux Debian11创建新用户和删除用户

一、 Debian 创建 新用户 1.创建新用户 首先&#xff0c;要创建用户&#xff0c;当前用户必须是 root 用户或者 sudo 用户。 使用下面adduser 命令创建一个用户名为test的sudo用户&#xff0c;按照提示输入密码&#xff0c;使用 adduser 命令&#xff0c;还会创建用户的主目…

Linux中创建新用户,设置ID与密码

如&#xff1a;新建用户admin&#xff0c;指定在/root家目录下&#xff0c;并指定用户id为6666&#xff0c;设置密码&#xff1a;admin123 添加用户 add&#xff1a;用于创建新的系统用户 语法&#xff1a;useradd[选项] 用户名 -d 指定用户的家目录&#xff08;默认用户名目录…

Linux手工创建新用户

准备工作&#xff08;配置流程的理解&#xff09; Linux中useradd命令即一系列文件操作的结合体&#xff0c;所以我们可以通过查看useradd命令来确认我们手工创建新用户需要完成的文件配置 找到man useradd中涉及的文件部分 对于手工创建用户有用的文件&#xff1a; /etc/pas…

linux创建/删除新用户

为了完成本关任务&#xff0c;你需要掌握如下知识&#xff1a; Linux创建用户命令Linux删除用户命令 Linux创建用户命令 Linux中使用useradd命令来创建一个新用户。 命令格式格式&#xff1a; useradd [命令参数] 参数 常见命令参数&#xff1a; -d<登入目录>&…