1)队列是一个有序列表,可以用数组或者链表实现
2)遵循先入先出的原则

使用数组实现队列

图片1.png
示意图
front:为对首标志,表示队列数组队首的下标-1
rear:为对尾标志,表示队列数组队尾的下标

  1. public class ArrayQueueDemo {
  2. public static void main(String[] args) {
  3. //创建队列
  4. ArrayQueue arrayQueue = new ArrayQueue(3);
  5. Scanner scanner = new Scanner(System.in);
  6. boolean loop = true;
  7. while (loop) {
  8. System.out.println("请输入:");
  9. System.out.println("1:展示数据");
  10. System.out.println("2:查看队首");
  11. System.out.println("3:添加数据");
  12. System.out.println("4:取出数据");
  13. System.out.println("5:退出");
  14. int key = scanner.nextInt();
  15. switch (key) {
  16. case 1:
  17. arrayQueue.showQueue();
  18. break;
  19. case 2:
  20. arrayQueue.peek();
  21. break;
  22. case 3:
  23. System.out.println("输入要添加的数据:");
  24. int n = scanner.nextInt();
  25. arrayQueue.addQueue(n);
  26. break;
  27. case 4:
  28. try{
  29. int data = arrayQueue.getQueue();
  30. System.out.println("取出数据:"+data);
  31. }catch (Exception e){
  32. String message = e.getMessage();
  33. System.out.println(message);
  34. }
  35. break;
  36. case 5:
  37. loop = false;
  38. break;
  39. default:
  40. System.out.println("输入有误");
  41. break;
  42. }
  43. }
  44. }
  45. }
  46. /**
  47. * 数组队列自定义类
  48. */
  49. class ArrayQueue{
  50. private int maxSize; //表示数组最大容量
  51. private int front; //指向队首
  52. private int rear; //指向队尾
  53. private int[] arr; //队列模拟数组
  54. public ArrayQueue(int maxSize){
  55. this.maxSize = maxSize;
  56. arr = new int[maxSize];
  57. front = -1; //指向队列前一个位置
  58. rear = -1; //指向队尾
  59. }
  60. //判断队列是否满
  61. public boolean isFull(){
  62. //队尾下标等于最大容量-1
  63. return rear == maxSize - 1;
  64. }
  65. //判断是否为空
  66. public boolean isEmpty(){
  67. return front == rear;
  68. }
  69. //添加数据
  70. public boolean addQueue(int n){
  71. //判断队列是否满
  72. if (isFull()){
  73. System.out.println("队列已满");
  74. return false;
  75. }
  76. rear++;
  77. arr[rear] = n;
  78. return true;
  79. }
  80. //取出数据
  81. public int getQueue(){
  82. //判断是否空
  83. if(isEmpty()){
  84. throw new RuntimeException("队列为空");
  85. }
  86. front++;
  87. return arr[front];
  88. }
  89. //显示队列的所有数据
  90. public void showQueue() {
  91. if (isEmpty()){
  92. System.out.println("队列空");
  93. return;
  94. }
  95. for(int i=0;i<arr.length;i++){
  96. System.out.println("arr["+i+"]="+arr[i]);
  97. }
  98. }
  99. //显示队列头数据
  100. public void peek(){
  101. //判断是否空
  102. if (isEmpty()) {
  103. System.out.println("队列空");
  104. return;
  105. }
  106. System.out.println(arr[front+1]);
  107. }
  108. }

以上实现存在问题:无法反复使用,因为队列中的下标会一直往前移动,导致队尾标志rear达到maxSize后无法再添加数据,而前面的空间由于front队首标志变大之后也无法继续使用

问题分析:
1)目前数组使用一次后就不能再用,没有达到复用的效果
2)将这个数组使用算法,改进成环形队列,使用取模:%

改写环形队列

思路分析:
1)front变量含义调整为:front指向队列的第一个元素
2)rear变量含义调整为:指向最后一个元素的后一个空的位置
3)队列满条件:(rear+1)%maxSize == front
4)队列空条件:rear == front
5)队列有效个数:(rear+maxSize-front)%maxSize //rear=1 front=0
图片2.png
图片3.png

  1. package com.cwl;
  2. /**
  3. * @Author Administrator
  4. * @Date 2021/2/19 0019 9:09
  5. * @Version 1.0
  6. */
  7. public class CircleArrayQueueDemo {
  8. public static void main(String[] args) {
  9. CircleArrayQueue circleArrayQueue = new CircleArrayQueue(6);
  10. circleArrayQueue.offer(0);
  11. circleArrayQueue.offer(1);
  12. circleArrayQueue.offer(2);
  13. circleArrayQueue.offer(3);
  14. circleArrayQueue.offer(4);
  15. circleArrayQueue.poll();//front=1
  16. circleArrayQueue.offer(5);//rear=0
  17. circleArrayQueue.poll();//front=2
  18. circleArrayQueue.offer(6);//rear=1
  19. circleArrayQueue.poll();//front=3
  20. circleArrayQueue.offer(7);//rear=2
  21. circleArrayQueue.poll();//front=4
  22. circleArrayQueue.offer(8);//rear=3
  23. int i = circleArrayQueue.hasElement();
  24. System.out.println("有效元素:"+i);
  25. circleArrayQueue.look();
  26. }
  27. }
  28. class CircleArrayQueue{
  29. private int maxSize; //最大容量,预留一个位置为空,避免前后端指针重合不易判断满和空
  30. private int rear; //队列后端指针,指向后端 + 1的位置
  31. private int front;//队列前端,指向头部
  32. private int[] arr;//队列,存放数据
  33. //构造器初始化数组容量
  34. public CircleArrayQueue(int maxSize){
  35. this.maxSize = maxSize;
  36. arr = new int[maxSize];
  37. }
  38. //判断满
  39. public boolean isFull(){
  40. return (rear + 1) % maxSize == front;
  41. }
  42. //判断空
  43. public boolean isEmpty(){
  44. return front == rear;
  45. }
  46. //返回有效数据个数,最大不超过maxSize-1
  47. public int hasElement(){
  48. return (rear + maxSize - front) % maxSize;
  49. }
  50. //入队,先判断是否满,若rear达到最大值maxSize将其取模为0
  51. public void offer(int val){
  52. if (isFull()){
  53. System.out.println("满");
  54. return;
  55. }
  56. arr[rear] = val;
  57. rear ++;
  58. if (rear == maxSize){
  59. rear = 0;
  60. }
  61. }
  62. //出队,先判断是否空,若front达到最大值maxSize将其取模为0
  63. public int poll(){
  64. if(isEmpty()){
  65. throw new RuntimeException("空");
  66. }
  67. int temp = arr[front];
  68. front ++;
  69. if (front == maxSize){
  70. front = 0;
  71. }
  72. return temp;
  73. }
  74. //查看队列头,先判断是否空,返回队列头的值,不会出队
  75. public int peek(){
  76. if (isEmpty()){
  77. throw new RuntimeException("空");
  78. }
  79. return arr[front];
  80. }
  81. //查看队列所有(有效值),当队列满时,实际上只有maxSize-1个有效值,从front开始遍历,大于等于maxSize时取模
  82. public void look(){
  83. if (isEmpty()){
  84. System.out.println("空");
  85. }
  86. for (int i = front;i < front + hasElement();i++){
  87. System.out.println("arr[" + i % maxSize+"]=" + arr[i % maxSize]);
  88. }
  89. }
  90. }