队列,循环队列为什么用空一个元素的位置

 本篇笔记是我在B站上跟着尚硅谷教程进行学习,记录的学习笔记,在学习中产生了疑问,并通过查找资料解决了相关问题。

队列介绍

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

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

  • front及rear分别记录队列前后端的下标,front随着数据的输出而改变,而rear则是随着数据输入而改变。

代码实现

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(add):添加数据到队列");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();arrayQueue.addQueue(value);break;case 'g':try {int res = arrayQueue.getQueue();System.out.println("取出数据:"+res);}catch (Exception e){System.out.println(e.getMessage());}break;case 'h':try {int res = arrayQueue.headQueue();System.out.println("队列头数据:"+res);}catch (Exception e){System.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 front==rear;}//添加数据到队列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.print(i+":"+ arr[i]+"\n");}}//显示队列的头数据,不是取出数据public  int headQueue(){if(isEmpty()){System.out.println("队列为空");throw new RuntimeException("队列为空");}return arr[front+1];}
}

问题分析并优化:

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

  • 我们要使用算法,将目前的数组改成一个环形的队列 取模%

数组环形队列思路:

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)%maxSize ==front时,我充满了疑惑,怎么算都觉得在rear已经表示最后元素的后一位了,这种情况下加一肯定是不对的,后来我查了一些资料。

那么,循环队列为什么用空一个元素的位置呢???

这个是根据需要来用的
循环队列中,由于入队时尾指du针向前追赶头指针;zhi出队时头指针向前追赶尾指针,造成dao队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。
解决这个问题的方法至少有三种:
①另设一布尔变量以区别队列的空和满;
②少用一个元素的空间。约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);
③使用一个计数器记录队列中元素的总数(即队列长度)。

代码实现(循环队列)

import java.util.Scanner;public class CicleArrayQueueDemo {public static void main(String[] args) {System.out.println("测试数组模拟环形数据");CircleArray queue = 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(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.println("取出数据:"+res);}catch (Exception e){System.out.println(e.getMessage());}break;case 'h':try {int res = queue.headQueue();System.out.println("队列头数据:"+res);}catch (Exception e){System.out.println(e.getMessage());}break;case 'e':scanner.close();loop = false;break;default:break;}}System.out.println("程序退出");}static class CircleArray{private int maxSize;private int front;//front就指向队列的第一个元素,就是是说arr[front]就是队列的第一个元素,front初始值为0;private int rear;//rear指向队列的最后一个元素的后一个位置,rear的初始值为0;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 front==rear;}//添加数据到队列public void addQueue(int n){if(isFull()){System.out.println("队列已满,不可加入数据");return;}arr[rear] = n;rear = (rear+1)%maxSize;}//从队列中取出数据public int getQueue(){if(isEmpty()){throw new RuntimeException("队列为空,不可取出数据");}int value = arr[front];front = (front+1) % maxSize;return value;}//求出当前队列的个数public int arrCount(){return (rear+maxSize-front)%maxSize;}//显示队列的中的所有数据public void showQueue(){if(isEmpty()){System.out.println("队列为空");return;}for (int i = front; i <front+arrCount(); i++) {System.out.print((i%maxSize)+":"+ arr[i%maxSize]+"\n");}}//显示队列的头数据,不是取出数据public  int headQueue(){if(isEmpty()){System.out.println("队列为空");throw new RuntimeException("队列为空");}return arr[front];}}
}

队列及循环队列为什么用空一个元素的位置相关推荐

  1. 数据结构之——队列与循环队列

    数据结构学习之--队列与循环队列 什么是队列(Queue) 队列基于动态数组的实现及时间复杂度分析 优化队列 循环队列(LoopQueue) 什么是队列(Queue) 队列(Queue)同栈(stac ...

  2. 数据结构-队列之循环队列

    将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上看成一个环,称为循环队列. 当队首指针q.front=MaxSize-1后,再前进一个位置就自动归0,可以通过除法取余运算(%)来实现. 初 ...

  3. 顺序队列,循环队列,链队列

    队列 先看队列接口和结点类 1. 顺序队列 2. 循环队列 3. 链队列 先看队列接口和结点类 package com.lovely.queue;/** * 2020年4月26日下午2:42:44* ...

  4. C/C++队列与循环队列

    C/C++数据结构 - 队列 循环队列 快速入门 介绍 1. 队列的定义 队列是一种线性存储结构,每次对队列的增删操作如下 增:在队列尾部添加元素 删(取出):在队列头部删除元素 这种数据存储方式遵循 ...

  5. 《恋上数据结构第1季》队列、双端队列、循环队列、循环双端队列

    队列(Queue) 队列 Queue 队列的接口设计 队列源码 双端队列 Deque 双端队列接口设计 双端队列源码 循环队列 Circle Queue 循环队列实现 索引映射封装 循环队列 – %运 ...

  6. java循环队列_Java版-数据结构-队列(循环队列)

    前情回顾 在上一篇,笔者给大家介绍了数组队列,并且在文末提出了数组队列实现上的劣势,以及带来的性能问题(因为数组队列,在出队的时候,我们往往要将数组中的元素往前挪动一个位置,这个动作的时间复杂度O(n ...

  7. 数据结构 - 队列 环形队列(循环队列)

    文章目录 队列介绍 数组模拟队列设计思路 数组模拟队列代码实现 环形队列相关知识说明 队列长度公式推导 数组模拟环形队列代码实现 队列介绍 队列是一个有序列表,可以用数组或是链表来实现. 遵循先入先出 ...

  8. 【霍洛维兹数据结构】栈和队列 | 动态循环队列 | 迷宫问题 | 表达式 | 多重栈多重队列

    前言: 最近在读霍罗维兹的<数据结构基础>(Fundamentals of Data Structures in C),本篇博客为阅读笔记和知识总结. 目录 Ⅰ. 栈(STACKS) 0x ...

  9. C语言 队列(循环队列)

    队列(循环队列) 队列是只允许在一端进行插入操作,在另一端进行删除操作的线性表.允许插入的一端称为队尾,允许删除的一端称为队头. 特性:先进先出. 循环队列 方式一: 队空:front==rear 队 ...

最新文章

  1. 汇总|实时性语义分割算法
  2. 容器删除元素后迭代器失效_使用迭代器遍历容器元素
  3. java 反序列化利用工具 marshalsec 使用简介
  4. Android LayoutInflater详解
  5. tomcat,很多时候,可以在服务server.xml中可以实现一些效果
  6. NetTiers模板中各个选项的一些解释
  7. Castle动态代理拦截器可构建可重启的流
  8. k8s与caas--容器云caas平台的落地实践
  9. C++标准库分析总结(一)
  10. gflags的使用(转载)
  11. docker具名和匿名挂载
  12. SolidWorks模型分享:皮带轮 免费模型下载
  13. 全国计算机高新技术模块,全国计算机信息高新技术考试模块总表.doc
  14. android 朋友圈上传图片,微信朋友圈终于可以发图片评论了!
  15. springboot整合腾讯云短信服务
  16. asp.net core部署在docker容器中运行
  17. php集成square功能(使用square/connect)
  18. (TVS)简介(瞬态抑制二极管)参数
  19. 关于 Window 的 UWP 应用本地回环限制以及限制解除方案
  20. 那些IT行业的经典定律

热门文章

  1. SQL常用函数、索引、视图、序列
  2. 基于Spring Boo微信公众号授权登录获取用户信息(附带完整源码)
  3. mysql8.0设置用户权限_MySQL8.0添加用户和权限
  4. MySQL异常:Incorrect key file for table '/tmp/#sql_37b_1.MYI'; try to repair it
  5. 递归实现格雷码GrayCode
  6. Python中RabbitMQ的使用
  7. 手机隐私保护不容乐观,洗大师能否解决后顾之忧?
  8. python配置国内镜像源操作步骤
  9. Emgu.CV训练自己的hog特征,可实现任意物体的检测
  10. 学而时习之(2):单边sar adc测热电偶温度