队列

1.队列的一个使用场景

银行排队的案例:

2、队列介绍

1) 队列是一个有序列表,可以用数组或是链表来实现。

2) 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取

3) 示意图:(使用数组模拟队列示意图)

3、数组模拟队列思路

队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队
列的最大容量。
因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标,
front 会随着数据输出而改变,而 rear 则是随着数据输入而改变,如图所示
当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤:思路分析
1)
将尾指针往后移:rear+1 , 当 front == rear 【空】
2)
若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear 所指的数组元素中,否则无法存入数据。
rear == maxSize - 1[队列满]
  • 代码实现 ---数组版
import java.util.Scanner;public class ArrayQueueDemo {public static void main(String[] args) {//测试一把// 创建一个队列ArrayQueue queue = 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(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 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++;// 让 rear 后移arr[rear] = n;}// 获取队列的数据, 出队列public int getQueue() {// 判断队列是否空if (isEmpty()) {// 通过抛出异常throw new RuntimeException("队列空,不能取数据");}front++; // 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];}}
问题分析并优化
1)
目前数组使用一次就不能用, 没有达到复用的效果
2)
将这个数组使用算法,改进成一个环形的队列 取模:%

4、数组模拟环形队列

对前面的数组模拟队列的优化,充分利用数组. 因此将数组看做是一个环形的。(通过取模的方式来实现即可)
分析说明:
1) 尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的
时候需要注意 (rear + 1) % maxSize == front 满]
2)
rear == front [空]
3)
分析示意图:
思路如下:
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
6.我们就可以在原来的队列上修改得到,一个环形队列
import java.util.Scanner;public class CircleArrayQueueDemo {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];//front = 0; //默认为0//rear = 0; // 默认为0,可以不写}//判断队列是否满,当队列满时,条件是(rear  + 1) % maxSize == front 【满】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;}rear++;// 让 rear 后移arr[rear] = n;}// 获取队列的数据, 出队列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]);}}//求出当前队列有效数据的个数public int size() {// rear = 2// front = 1// maxSize = 3return (rear + maxSize - front) % maxSize;}// 显示队列的头数据, 注意不是取出数据public int headQueue() {// 判断if (isEmpty()) {throw new RuntimeException("队列空的,没有数据~~");}return arr[front];}}

数据结构韩顺平版(2)相关推荐

  1. 【尚硅谷|韩顺平】数据结构和算法

    文章目录 前言: 数据结构和算法 数据结构和算法的概述 数据结构和和算法的关系 数据结构 线性结构和非线性结构 非线性结构 稀疏 sparsearray 数组 基本介绍: 稀疏数组的处理方法是: 应用 ...

  2. 尚硅谷Java数据结构和java算法,韩顺平数据结构和算法课后作业01

    尚硅谷Java数据结构和java算法,韩顺平数据结构和算法课后作业第一题 要求: 1)在前面的基础上,将稀疏数组保存到磁盘上,比如map.data 2) 恢复原来的数组时,读取map.data进行恢复 ...

  3. 数据结构 - Java -韩顺平 图解Java数据结构和算法

    数据结构 Lesson 1 数据结构的知识总结 1. 几个经典的算法面试题 2. 线性结构与非线性结构 2.1 稀疏数组 sparsearray 2.2 队列 2.2.1 顺序队列: 2.2.2 环形 ...

  4. 韩顺平老师坦克大战优化版

    一.项目介绍 1.前言 基于韩顺平老师坦克大战的框架和思路,进行了一些优化.编码上尽量按照阿里的代码规约:有非常详尽的注释:引入了线程池,线程安全集合类,原子类等:通过这个小项目的学习,可以深入地理解 ...

  5. Java集合深入剖析【韩顺平老师版】

    Java集合知识体系[思维导图] 1.集合体系 1.1.为什么使用集合? 1.数组的不足 长度固定,不能更改 存储的必须是同一类型的元素(基本类型或引用类型) 增加.删除元素比较麻烦 2.集合的优势 ...

  6. 韩顺平 数据结构与算法 (12_6) 树结构应用部分_赫夫曼编码实践——数据解码

    赫夫曼编码实践--数据解码 代码实现(承袭压缩的代码) package DataStructures.huffmanTree;import javax.print.DocFlavor; import ...

  7. 韩顺平MySQL万字笔记

    数据库 数据库存储位置 数据库的存储位置取决于你把数据库放建在哪,你建你在你电脑本地,那数据库就在本地.你放服务器上,那数据库就在服务器上.本质跟你在本地新建一个Excel表,和在百度云上建,是同一个 ...

  8. 韩顺平老师讲解13个自学编程的坑

    文章目录 前言 内容 误区一 不注重基础,什么技术火就学什么 误区二 总是纠结学最好的编程语言 误区三 喜欢看不喜欢动手 误区四 没有认识到,听懂和能使用时两回事 误区五 很少做笔记,也不去画思维导图 ...

  9. 2021韩顺平图解linux

    韩顺平图解Linux全面升级 https://www.bilibili.com/video/BV1Sv411r7vd 27 小时 .153 讲, 2021 韩顺平 一周学会Linux 简介 目录 P0 ...

  10. Mysql安装(转自韩顺平教育)

    Mysql5.7.19 解压版安装配置详细教程 软件下载 Mysql5.7地址:https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-w ...

最新文章

  1. oracle数据库硬恢复,ORACLE数据库恢复技术
  2. 检测数(二进制形式)中1的个数
  3. 【正一专栏】从“欣欣像蓉”谈网络暴力
  4. 【带你入门】java网络编程
  5. 【Android】系统目录理解
  6. 二分图最大权匹配算法KM
  7. .net core 源码解析-web app是如何启动并接收处理请求
  8. 7-41 PAT排名汇总 (25 分)(详解+思路+重写sort函数)兄弟们冲呀呀呀呀呀呀呀
  9. 银行支行信息 银行卡归属地
  10. Android WebView:这是一份全面 详细的WebView学习指南
  11. K8S+Harbor+gluster+haproxy 实践加坑
  12. 使用Python把PowerPoint文件转换为配乐MP4视频
  13. Linux下selinux简单梳理
  14. 帝国7.2 php5.2,帝国CMS7.2版升级到7.5版的详细步骤方法(已测)
  15. linux windows市场占有率,Windows 10市场份额罕见倒退:Win7也跌了 Linux暴增111%
  16. 制作windows7虚拟机镜像并配置网络
  17. IDEA web.xml版本过低怎么生成新的
  18. 高德地图API定位失败 浏览器定位 IP定位
  19. 《读书是教师最好的修行》读后感优秀范文2200字
  20. 测试小故事6:术业有专攻

热门文章

  1. 经典日常英语口语回汇总大全
  2. 有个exe文件删不掉怎么办
  3. K8S CRD 资源对象删除不掉
  4. [维修案例] 艾美特电风扇(FS4085R)不能调风量维修
  5. 使用图灵机器人笑话功能提高微信公众帐号活跃度
  6. WORD中图片叠加背景融合的方法
  7. 对比7种分布式事务方案,还是偏爱阿里开源的Seata,真香!(原理+实战)
  8. 计算机如何快速切换窗口,如何快速切换电脑页面
  9. UINO优锘:竞速“元宇宙”,中国能凭借数字孪生技术突围吗?
  10. python学习:用两种思路计算质数与合数