队列是一个有序列表,可以用数组或是链表来实现。
遵循先进先出的原则。
image.png

1、数组模拟队列思路

队列本身是有序队列,若用数组结构来存储队列的数据,则队列数据的声明如下图,其中maxSize是该队列的最大容量。
因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front 及 rear 分别记录队列前后端的下标,front 会随着数据输出而改变,如图所示:
image.png
当我们将数据存入队列时称为“addQueue”, addQueue 的处理需要有两个步骤: 思路分析
1)将尾针往后移: rear+1,当front == rear【空】
2)若尾指针 rear 小于最大下标 maxSize-1 ,则将数据存入rear若之的数组元素中,否则无法存入数据。rear ==maxSize - 1【队列满】
代码如下:

  1. package com;
  2. import java.util.Scanner;
  3. public class ArrayQueueDemo {
  4. public static void main(String[] args) {
  5. ArrayQueue Queue = new ArrayQueue(3);
  6. char key = ' ';//接受用户输入
  7. Scanner scan = new Scanner(System.in);
  8. boolean loop = true;
  9. // 输出一个菜单
  10. while(loop){
  11. System.out.println("s(show): 显示队列");
  12. System.out.println("e(exit): 退出程序");
  13. System.out.println("a(add): 添加数据到队列");
  14. System.out.println("g(get): 从队列取出数据");
  15. System.out.println("h(head): 查看队列头的数据");
  16. key =scan.next().charAt(0);//接受一个字符
  17. switch (key){
  18. case 's':
  19. Queue.showQueue();
  20. break;
  21. case 'a':
  22. System.out.println("请输入一个数字");
  23. int value = scan.nextInt();
  24. Queue.addQueue(value);
  25. break;
  26. case 'g':
  27. try {
  28. int res = Queue.getQueue();
  29. System.out.printf("取出的数据是:%d\n",res);
  30. }catch (Exception e){
  31. System.out.println(e.getMessage());
  32. }
  33. break;
  34. case 'h':
  35. try {
  36. int res = Queue.headQueue();
  37. System.out.printf("队列头的数据是:%d\n",res);
  38. }catch (Exception e){
  39. System.out.println(e.getMessage());
  40. }
  41. break;
  42. case 'e':
  43. scan.close();
  44. loop = false;
  45. default:
  46. break;
  47. }
  48. }
  49. System.out.println("程序退出");
  50. }
  51. }
  52. class ArrayQueue{
  53. private int maxSize;//表示数组的最大容量
  54. private int front;// 队列头
  55. private int rear;// 队列尾
  56. private int[] arr;
  57. // 创建队列的构造器
  58. public ArrayQueue(int arrMaxSize){
  59. maxSize = arrMaxSize;
  60. arr = new int[arrMaxSize];
  61. front = -1; //指向队列头部,分析出front是指向队列头的前一个位置。
  62. rear = -1;// 指向队列尾,指向队列尾的数据(即就是队列最后一个数据)
  63. }
  64. // 判断队列数据是否满
  65. public boolean isFull(){
  66. return rear == maxSize - 1;
  67. }
  68. public void addQueue(int n){
  69. // 判断队列是否满
  70. if(isFull()){
  71. System.out.println("队列满,不能加入数据");
  72. return;
  73. }
  74. rear++;// 让rear后移
  75. arr[rear] = n;
  76. }
  77. // 判断是否为空
  78. public boolean isEmpty(){
  79. return rear == front;
  80. }
  81. // 获取队列数据
  82. public int getQueue(){
  83. if (isEmpty()){
  84. //通过抛出异常
  85. throw new RuntimeException("队列为空");}
  86. front++;// 将front后移
  87. return arr[front];
  88. }
  89. // 显示队列所有数据
  90. public void showQueue(){
  91. // 遍历
  92. if(isEmpty()){
  93. System.out.println("队列空的,没有数据~~~");
  94. return;
  95. }
  96. for (int i=0; i<arr.length;i++){
  97. System.out.printf("arr[%d]=%d\n", i, arr[i]);
  98. }
  99. }
  100. // 显示队列的头数据,注意不是取出数据
  101. public int headQueue(){
  102. //判断
  103. if(isEmpty()){
  104. throw new RuntimeException("队列为空");
  105. }
  106. return arr[front + 1];
  107. }
  108. }

注意:以上代码所实现的是一个一次性队列,不能添加,因为头front和尾rear是往后移动的,所以要进行优化为环形队列,通过取模来实现。

2. 数组模拟环形队列

image.png

image.png

利用模运算:rear = rear + 1 ;if (rear==maxsize) rear = 0
可转化为:rear = (rear + 1)%maxsize
出队则:
front = (front +1)%maxsize
遍历:(rear+maxsize-front)%maxsize

  1. public class ArrayQueueDemo2 {
  2. public static void main(String[] args) {
  3. circleArrayQueue Queue = new circleArrayQueue(4);
  4. char key = ' ';//接受用户输入
  5. Scanner scan = new Scanner(System.in);
  6. boolean loop = true;
  7. // 输出一个菜单
  8. while(loop){
  9. System.out.println("s(show): 显示队列");
  10. System.out.println("e(exit): 退出程序");
  11. System.out.println("a(add): 添加数据到队列");
  12. System.out.println("g(get): 从队列取出数据");
  13. System.out.println("h(head): 查看队列头的数据");
  14. key =scan.next().charAt(0);//接受一个字符
  15. switch (key){
  16. case 's':
  17. Queue.showQueue();
  18. break;
  19. case 'a':
  20. System.out.println("请输入一个数字");
  21. int value = scan.nextInt();
  22. Queue.addQueue(value);
  23. break;
  24. case 'g':
  25. try {
  26. int res = Queue.getQueue();
  27. System.out.printf("取出的数据是:%d\n",res);
  28. }catch (Exception e){
  29. System.out.println(e.getMessage());
  30. }
  31. break;
  32. case 'h':
  33. try {
  34. int res = Queue.headQueue();
  35. System.out.printf("队列头的数据是:%d\n",res);
  36. }catch (Exception e){
  37. System.out.println(e.getMessage());
  38. }
  39. break;
  40. case 'e':
  41. scan.close();
  42. loop = false;
  43. break;
  44. default:
  45. break;
  46. }
  47. }
  48. System.out.println("程序退出");
  49. }
  50. }
  51. class circleArrayQueue{
  52. private int maxSize;//表示数组的最大容量
  53. private int front;// 队列头
  54. private int rear;// 队列尾
  55. private int[] arr;
  56. // 创建队列的构造器
  57. public circleArrayQueue(int arrMaxSize){
  58. maxSize = arrMaxSize;
  59. arr = new int[arrMaxSize];
  60. //front = 0; //指向队列第一个元素,分析出front是指向队列头的前一个位置。
  61. //rear = 0;// 指向队列的最后一个位置,因为希望空出一个位置,指向队列尾的数据(即就是队列最后一个数据)
  62. }
  63. // 判断队列数据是否满
  64. public boolean isFull(){
  65. return (rear+1)%maxSize == front;
  66. }
  67. public void addQueue(int n){
  68. // 判断队列是否满
  69. if(isFull()){
  70. System.out.println("队列满,不能加入数据");
  71. return;
  72. }
  73. arr[rear] = n;
  74. rear = (rear+1)% maxSize;//考虑取模
  75. }
  76. // 判断是否为空
  77. public boolean isEmpty(){
  78. return rear == front;
  79. }
  80. // 获取队列数据
  81. public int getQueue(){
  82. if (isEmpty()){
  83. //通过抛出异常
  84. throw new RuntimeException("队列为空");
  85. }
  86. int value = arr[front];
  87. front = (front+1)%maxSize;// 将front后移,考虑取模
  88. return value;
  89. }
  90. // 显示队列所有数据
  91. public void showQueue(){
  92. // 遍历
  93. if(isEmpty()){
  94. System.out.println("队列空的,没有数据~~~");
  95. return;
  96. }
  97. for (int i=front; i<front + size();i++){
  98. System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
  99. }
  100. }
  101. //求当前队列有效数据的个数
  102. public int size(){
  103. return (rear + maxSize - front) % maxSize;
  104. }
  105. // 显示队列的头数据,注意不是取出数据
  106. public int headQueue(){
  107. //判断
  108. if(isEmpty()){
  109. throw new RuntimeException("队列为空");
  110. }
  111. return arr[front];
  112. }
  113. }