【数据结构与算法】——队列(Queue)
队列(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)的更多相关文章
- Airport Simulation (数据结构与算法 – 队列 / Queue 的应用)
Airport Simulation 是数据结构与算法教材中用于演示Queue的一个小程序(大多数教师似乎会跳过这个练习).主程序会通过输入总的运行时间.队列里可以等待的最多飞机数量,平均每个时间单元 ...
- [数据结构与算法]队列Queue 的多种实现
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- javascript数据结构与算法---队列
javascript数据结构与算法---队列 队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素.队列用于存储按顺序排列的数据,先进先出,这点和栈不一样(后入先出).在栈中,最后入栈的元素 ...
- JavaScript数据结构与算法-队列练习
队列的实现 // 队列类 function Deque () { this.dataStore = []; this.enqueueFront = enqueueFront; this.enqueue ...
- python数据结构与算法——队列
队列结构可以使用数组来模拟,只需要设定头和尾的两个标记 参考自<啊哈> # 按书中的代码会出现索引越界的问题(书中申请了超量的空间) # 尝试令tai初始为len(q)-1则不会出错但少了 ...
- 每周一练 之 数据结构与算法(Queue)
这是第二周的练习题,这里补充下咯,五一节马上就要到了,自己的计划先安排上了,开发一个有趣的玩意儿. 下面是之前分享的链接: 1.每周一练 之 数据结构与算法(Stack) 2.每周一练 之 数据结构与 ...
- C语言- 基础数据结构和算法 - 队列的顺序存储
听黑马程序员教程<基础数据结构和算法 (C版本)>, 照着老师所讲抄的, 视频地址https://www.bilibili.com/video/BV1vE411f7Jh?p=1 喜欢的朋友 ...
- JS数据结构与算法-队列结构
队列结构 一.认识队列 受限的线性结构: 我们已经学习了一种受限的线性结构:栈结构. 并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的 效果. 下面,我们再来学习另外一个受限的数据结构: ...
- JavaScript数据结构和算法----队列
前言 队列和栈很像,只是用了不同的原则.队列是遵循先进先出(FIFO)原则的一组有序的的项,队列在尾部添加新元素,从顶部移除元素.最新添加的元素必须必须排队在队列的,末尾.可以想象食堂排队买饭的样子. ...
- js数据结构与算法——队列
<script> //创建一个队列 function Queue(){ let items = []; //向队尾添加一个新的项 this.enqueue = function(eleme ...
随机推荐
- Linux程序设计——Linux基础
1. 什么是Linux 1)Linux系统是一种自由和开放源代码的类UNIX的完整操作系统. 2)林纳斯·本纳第克特·托瓦兹(LinusBenedictTorvalds,1969年~) 3)诞生于19 ...
- MySQL 事务特征 & 隔离级别
数据库事务特征 Atomicity 原子性 事务是一个原子性质的操作单元,事务里面的对数据库的操作要么都执行,要么都不执行, Consistent 一致性 在事务开始之前和完成之后,数据都必须保持一致 ...
- Oracle数据库故障处理方法
1.启动数据库报错:ORA-01102:cannot mount database in EXCLUSIVE mode 给客户处理oracle故障,遇到如下报错: 以sys登录至数据库,执行shutd ...
- linux多线程模拟银行家算法
题外话: 这应该是最近有点难度的作业了,起码比之前的理发师,读写,哲学家问题要难. 但是做好程序的结构,自顶向下,就还是不难的. 银行家算法简介: 代码: init() ...
- ARM汇编---程序获取符号的物理地址
在移植u-boot的过程看到过u-boot在重定向时的实现,当时不知道怎么就觉得很好理解就把这个知识点没怎么深入的理解,最近在看华为的鸿蒙OS在Cortex-A平台上的实现过程时再次遇到一时间看不太懂 ...
- tensorflow-gpu+"Failed to create session"
成因: 未给系统指定相应使用的GPU 解决: 层面1: 针对单个程序: CUDA_VISIBLE_DEVICES=0 python main.py import os; os.environ['CUD ...
- ReactDOM API All In One
ReactDOM API All In One React DOM API render() hydrate() unmountComponentAtNode() findDOMNode() crea ...
- React + GraphQL 2020 速成课程
React + GraphQL 2020 速成课程 technologies React (to build our user interface) GraphQL (to get and chang ...
- Dart DevTools & Flutter
Dart DevTools & Flutter https://flutter.dev/docs/development/tools/devtools/overview https://dar ...
- SVG to GeoJSON
SVG to GeoJSON GEOJSON https://geojson.org/ http://geojson.io/ https://github.com/mapbox/geojson.io/ ...