队列

队列介绍

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

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

-》示意图:(使用是数组模拟队列示意图)

 

 -》其中maxsSize是该队列的最大容量。

-》因为队列的输出、输入分别是从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数组输出而改变,而rear则是随着数据输入而改变

 

-》当我们将数据存入队列时称为“addQueue”,addQueue的处理需要有两个步骤:思路分析

(1)将尾指针往后移:rear+1, 当front==rear【空】

(2)若尾指针rear小于队列的最大下表maxSize-1,则将数据存入rear所指的数组元素中,否则无法存入数据。

 rear==maxSize-1【队列满】

 

-》代码实现

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

 

-》问题优化

(1)目前数组使用一次就不能使用, 没有达到复用的效果。

(2)将这个数组使用算法,改进成一个环形的队列 取模:%

 

数组模拟环形队列

 

对前面的数组模拟队列的优化,充分利用数组。因此将数组看做是一个环形的。(通过取模的方式来实现即可

-》分析说明:

(1)尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意(rear+1)%maxSize==front【满】

(2)rear==front【空】

(3)分析示意图:

 

 -》代码实现:

  1 package com.atguigu.queue;
  2 
  3 import java.util.Scanner;
  4 
  5 public class CircleArrayQueueDemo {
  6 
  7     public static void main(String[] args) {
  8         
  9         //测试一把
 10         System.out.println("测试数组模拟环形队列的案例~~~");
 11         
 12         // 创建一个环形队列
 13         CircleArray queue = new CircleArray(4); //说明设置4, 其队列的有效数据最大是3
 14         char key = ' '; // 接收用户输入
 15         Scanner scanner = new Scanner(System.in);//
 16         boolean loop = true;
 17         // 输出一个菜单
 18         while (loop) {
 19             System.out.println("s(show): 显示队列");
 20             System.out.println("e(exit): 退出程序");
 21             System.out.println("a(add): 添加数据到队列");
 22             System.out.println("g(get): 从队列取出数据");
 23             System.out.println("h(head): 查看队列头的数据");
 24             key = scanner.next().charAt(0);// 接收一个字符
 25             switch (key) {
 26             case 's':
 27                 queue.showQueue();
 28                 break;
 29             case 'a':
 30                 System.out.println("输出一个数");
 31                 int value = scanner.nextInt();
 32                 queue.addQueue(value);
 33                 break;
 34             case 'g': // 取出数据
 35                 try {
 36                     int res = queue.getQueue();
 37                     System.out.printf("取出的数据是%d\n", res);
 38                 } catch (Exception e) {
 39                     // TODO: handle exception
 40                     System.out.println(e.getMessage());
 41                 }
 42                 break;
 43             case 'h': // 查看队列头的数据
 44                 try {
 45                     int res = queue.headQueue();
 46                     System.out.printf("队列头的数据是%d\n", res);
 47                 } catch (Exception e) {
 48                     // TODO: handle exception
 49                     System.out.println(e.getMessage());
 50                 }
 51                 break;
 52             case 'e': // 退出
 53                 scanner.close();
 54                 loop = false;
 55                 break;
 56             default:
 57                 break;
 58             }
 59         }
 60         System.out.println("程序退出~~");
 61     }
 62 
 63 }
 64 
 65 
 66 class CircleArray {
 67     private int maxSize; // 表示数组的最大容量
 68     //front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素 
 69     //front 的初始值 = 0
 70     private int front; 
 71     //rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
 72     //rear 的初始值 = 0
 73     private int rear; // 队列尾
 74     private int[] arr; // 该数据用于存放数据, 模拟队列
 75     
 76     public CircleArray(int arrMaxSize) {
 77         maxSize = arrMaxSize;
 78         arr = new int[maxSize];
 79     }
 80     
 81     // 判断队列是否满
 82     public boolean isFull() {
 83         return (rear  + 1) % maxSize == front;
 84     }
 85     
 86     // 判断队列是否为空
 87     public boolean isEmpty() {
 88         return rear == front;
 89     }
 90     
 91     // 添加数据到队列
 92     public void addQueue(int n) {
 93         // 判断队列是否满
 94         if (isFull()) {
 95             System.out.println("队列满,不能加入数据~");
 96             return;
 97         }
 98         //直接将数据加入
 99         arr[rear] = n;
100         //将 rear 后移, 这里必须考虑取模
101         rear = (rear + 1) % maxSize;
102     }
103     
104     // 获取队列的数据, 出队列
105     public int getQueue() {
106         // 判断队列是否空
107         if (isEmpty()) {
108             // 通过抛出异常
109             throw new RuntimeException("队列空,不能取数据");
110         }
111         // 这里需要分析出 front是指向队列的第一个元素
112         // 1. 先把 front 对应的值保留到一个临时变量
113         // 2. 将 front 后移, 考虑取模
114         // 3. 将临时保存的变量返回
115         int value = arr[front];
116         front = (front + 1) % maxSize;
117         return value;
118 
119     }
120     
121     // 显示队列的所有数据
122     public void showQueue() {
123         // 遍历
124         if (isEmpty()) {
125             System.out.println("队列空的,没有数据~~");
126             return;
127         }
128         // 思路:从front开始遍历,遍历多少个元素
129         // 动脑筋
130         for (int i = front; i < front + size() ; i++) {
131             System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
132         }
133     }
134     
135     // 求出当前队列有效数据的个数
136     public int size() {
137         // rear = 2
138         // front = 1
139         // maxSize = 3 
140         return (rear + maxSize - front) % maxSize;   
141     }
142     
143     // 显示队列的头数据, 注意不是取出数据
144     public int headQueue() {
145         // 判断
146         if (isEmpty()) {
147             throw new RuntimeException("队列空的,没有数据~~");
148         }
149         return arr[front];
150     }
151 }

 

posted @ 2020-07-19 21:13  cire  阅读(148)  评论(0)    收藏  举报
/* 看板娘 */