队列(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. Redis 搭建与配置

    Redis 简介 Redis 是一款开源的,ANSI C 语言编写的,高级键值(Key-Value)缓存和支持永久存储 NoSQL 数据库产品, Redis 采用内存(In-Memory)数据集(Da ...

  2. 【转】Kubernetes scheduler学习笔记

    简介 Kubernetes是一个强大的编排工具,可以用来很方便的管理许多台机器,为了使机器的资源利用率提高,同时也尽可能的把压力分摊到各个机器上,这个职责就是由scheduler来完成的. Kuber ...

  3. Linux网络文件下载

    wget 以网络下载 maven 包为例 wget -c http://mirrors.shu.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-ma ...

  4. DCL 数据控制语言

    目录 授予权限(GRANT) 回收权限(REVOTE) 授予权限(GRANT) # 语法 mysql> help grant; Name: 'GRANT' Description: Syntax ...

  5. Python-collections模块之defaultdict

    defaultdict defaultdict 是 dict 类型的子类,正如其名,初始化时,可以给key指定默认值,什么意思呢?直接看代码.如果是普通的dict对象,访问一个不存在的key时,会报错 ...

  6. woj1008feedinganimals2-贪心-网络流

    title: woj1008feedinganimals2-贪心-网络流 date: 2020-03-07 categories: acm tags: [acm,woj,网络流,贪心] 中等题. 标准 ...

  7. Leetcode(28)-实现strStr()

    实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始).如果不存在,则返 ...

  8. sdut2879 枚举起点DP

    这个题和乌龟棋之类的DP差不多要学会缩减状态 就是,,我们只需枚举当前这个人是谁,选什么颜色,A用了多少,B用了多少 C用了多少我们就不用枚举了,知道选了多少人,A,B用了多少,你还不知C用了多少么, ...

  9. git branch All In One

    git branch All In One Git Branch Management https://git-scm.com/book/en/v2/Git-Branching-Branch-Mana ...

  10. CSS multi colors circle

    CSS multi colors circle <!DOCTYPE html> <html lang="zh-Hans"> <head> < ...