队列(Queue)的一个使用场景

银行排队的案例:

队列(Queue)介绍

  • 队列是一个有序列表,可以用数组或是链表来实现。
  • 遵循先入先出的原则。即:先存入队列的数据,要先取出来。后存入的要后取出来。

数组模拟队列

  • 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图,其中maxSize是该队列的最大容量。

  • 因为队列的输出、输入分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变的。如图所示:

思路分析:

当我们将数据存入队列时称为“addQueue”,addQueue的处理需要有两个步骤:

  • 将尾指针往后移:rear+1,当front == rear【空】
  • 若尾指针rear小于队列的最大下标maxSize-1,则将数据存入rear所指的数组元素中,否则无法存入数据。rear == maxSize-1【队列满】

代码实现

import java.util.Scanner;

public class ArrayQueueDemo {

	public static void main(String[] args) {
// 测试
//创建一个队列
ArrayQueue arrayQueue = new ArrayQueue(3);
char 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(show):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
key = scanner.next().charAt(0);
switch (key) {
case 's'://显示队列
arrayQueue.showQueue();
break;
case 'a'://添加数据到队列
System.out.println("请输入一个数字:");
int value = scanner.nextInt();
System.out.println(value);
arrayQueue.addQueue(value);
break;
case 'g'://从队列取出数据
try {
int res = arrayQueue.getQueue();
System.out.printf("取出数据是%d\n",res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'h'://查看队列头的数据
try {
int res = arrayQueue.headQueue();
System.out.printf("队列头的数据是%d\n",res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'e'://退出程序
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出~~");
} }
//使用数组模拟队列-编写一个ArrayQueue类
class ArrayQueue {
private int maxSize;//表示数组最大容量
private int front;//队列头部
private int rear;//队列尾部
private int[] arr;//该数组用于存放数据,模拟队列 //创建队列的构造器
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int [maxSize];
front = -1;//队列头部,指向队列头的前一个位置
rear = -1;//队列尾部,指向队列尾的数据(就是队列最后一个数据)
}
//判断队列是否满
public boolean isFull() {
return rear == maxSize - 1;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
//添加数据到队列
public void addQueue(int n) {
//判断队列是否已满
if(isFull()) {
System.out.println("队列已满,无法加入数据~~");
return;
}
rear ++;
arr[rear] = n;
}
//获取队列的数据(出队列)
public int getQueue() {
if(isEmpty()) {
throw new RuntimeException("队列为空,无法取数据~~");
}
front ++;
return arr[front];
}
//显示所有数据
public void showQueue() {
//判断是否为空
if(isEmpty()) {
System.out.println("队列为空,没有数据~~");
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.printf("arr[%d]=%d\n",i,arr[i]);
}
}
//显示队列的头数据,(不是取出数据)
public int headQueue() {
if(isEmpty()) {
throw new RuntimeException("队列为空,无法取数据~~");
}
return arr[front + 1];
}
}

输出结果:

问题分析

目前数组使用一次就不能使用了,没有达到复用的效果

优化

  • 对前面的数组模拟队列的优化,充分利用数组,因此将数组看做是有个环形的。(通过取模的方式来实现即可)

    说明:

    • 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意,(rear+1)%maxSize == front[满]
    • rear == front[空]

    思路如下:

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

    有了这样一个思路,我们就可以在原来队列上修改得到一个环形队列。

优化后的代码

import java.util.Scanner;

/**
* @Author ITfxsen https://www.cnblogs.com/fxsenblog/
* @Time 2021-3-12 13:11:26
* @Version 1.0
* <p>Description:环形数组队列Demo</p>
*/
public class CircleArrayQueueDemo { public static void main(String[] args) {
// 测试
System.out.println("测试数组模拟环形队列~~");
//创建一个环形队列
CircleArray circleArray = new CircleArray(4);//队列有效数据最大3
char 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(show):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head):查看队列头的数据");
key = scanner.next().charAt(0);
switch (key) {
case 's'://显示队列
circleArray.showQueue();
break;
case 'a'://添加数据到队列
System.out.println("请输入一个数字:");
int value = scanner.nextInt();
System.out.println(value);
circleArray.addQueue(value);
break;
case 'g'://从队列取出数据
try {
int res = circleArray.getQueue();
System.out.printf("取出数据是%d\n",res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'h'://查看队列头的数据
try {
int res = circleArray.headQueue();
System.out.printf("队列头的数据是%d\n",res);
} catch (Exception e) {
// TODO: handle exception
System.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的初始值=0。
private int front;//队列头部
//rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置。因为希望空出一个空间作为约定,rear的初始值=0。
private 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() {
return (rear + maxSize - front) % maxSize;
}
//显示队列的头数据,(不是取出数据)
public int headQueue() {
if(isEmpty()) {
throw new RuntimeException("队列为空,无法取数据~~");
}
return arr[front];
}
}

运行截图:

【数据结构与算法】——队列(Queue)的更多相关文章

  1. Airport Simulation (数据结构与算法 – 队列 / Queue 的应用)

    Airport Simulation 是数据结构与算法教材中用于演示Queue的一个小程序(大多数教师似乎会跳过这个练习).主程序会通过输入总的运行时间.队列里可以等待的最多飞机数量,平均每个时间单元 ...

  2. [数据结构与算法]队列Queue 的多种实现

    声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...

  3. javascript数据结构与算法---队列

    javascript数据结构与算法---队列 队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出).在栈中,最后入栈的元素 ...

  4. JavaScript数据结构与算法-队列练习

    队列的实现 // 队列类 function Deque () { this.dataStore = []; this.enqueueFront = enqueueFront; this.enqueue ...

  5. python数据结构与算法——队列

    队列结构可以使用数组来模拟,只需要设定头和尾的两个标记 参考自<啊哈> # 按书中的代码会出现索引越界的问题(书中申请了超量的空间) # 尝试令tai初始为len(q)-1则不会出错但少了 ...

  6. 每周一练 之 数据结构与算法(Queue)

    这是第二周的练习题,这里补充下咯,五一节马上就要到了,自己的计划先安排上了,开发一个有趣的玩意儿. 下面是之前分享的链接: 1.每周一练 之 数据结构与算法(Stack) 2.每周一练 之 数据结构与 ...

  7. C语言- 基础数据结构和算法 - 队列的顺序存储

    听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...

  8. JS数据结构与算法-队列结构

    队列结构 一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构. 并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的 效果. 下面,我们再来学习另外一个受限的数据结构: ...

  9. JavaScript数据结构和算法----队列

    前言 队列和栈很像,只是用了不同的原则.队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素.最新添加的元素必须必须排队在队列的,末尾.可以想象食堂排队买饭的样子. ...

  10. js数据结构与算法——队列

    <script> //创建一个队列 function Queue(){ let items = []; //向队尾添加一个新的项 this.enqueue = function(eleme ...

随机推荐

  1. Gym 101128J Saint John Festival(凸包 + 二分判点和凸包关系)题解

    题意:给你一堆黑点一堆红点,问你有最多几个黑点能找到三个红点,使这个黑点在三角形内? 思路:显然红点组成的凸包内的所有黑点都能做到.但是判断黑点和凸包的关系朴素方法使O(n^2),显然超时.那么我现在 ...

  2. Fetch & POST

    Fetch & POST fetch( `http://10.1.5.202/deploy/http/send/viewtree`, { method: "POST", m ...

  3. How to change Linux Terminal display username

    How to change Linux Terminal display username 如何更改 Linux Terminal 显示的用户名 (base) ➜ ~ whoami xgqfrms-m ...

  4. p5.js

    p5.js p5.j​​s是一个用于创意编码的JavaScript库,其重点是使艺术家,设计师,教育者,初学者以及其他任何人都可以访问并包含所有编码! https://p5js.org/ https: ...

  5. 来必力 & Disqus

    来必力 & Disqus 正在载入来必力 https://livere.com 个人博客-双评论系统(来必力与Disqus) https://tianbozhang.coding.me/com ...

  6. super fast sort algorithm in js

    super fast sort algorithm in js sort algorithm Promise.race (return the fast one) Async / Await // c ...

  7. Contributor License Agreement

    Contributor License Agreement CLA https://cla.js.foundation/lodash/lodash?pullRequest=4756 https://g ...

  8. taro scroll tabs 滚动标签 切换

    taro scroll tabs 滚动标签 切换 https://www.cnblogs.com/lml-lml/p/10954069.html https://developers.weixin.q ...

  9. script async / defer

    script async / defer preload / prefetch https://abc.xgqfrms.xyz/ https://javascript.info/script-asyn ...

  10. 实用Macbook软件系列

    Macbook Software 实用Macbook软件系列 我的Mac都装了哪些软件 鉴于很多小伙伴刚刚由win系统转换到mac,一开始会有很多不适应的地方,所以本期文章准备给大家介绍下mac上一些 ...