队列:先进先出
- 队列是一个有序列表,可以用数组实现或者链表实现。
- 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入队列的数据,要后取出。
顺序队列
思路:
- maxSize是该队列的对大容量。front和rear分别记录队列的前后端下标,front会随着数据的输出而改变,rear随着数据输入而改变。
- rear指向最后一个数据,添加数据的时候需要先rear++再添加数据。
- front指向第一个数据的上一个位置,输出数据的时候需要先front++再输出数据。
- 初始:
front = -1 rear = -1
- 队列为空条件:
front = rear
- 队列已满条件:
rear = maxSize - 1
代码实现:
package queue;
import java.text.ParseException;
import java.text.SimpleDateFormat;
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(quit):退出程序");
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 'e':
scanner.close();
loop = false;
break;
case 'a':
System.out.println("请输入一个数据:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g':
try {
int get = arrayQueue.getQueue();
System.out.printf("取出的数据为:%d", get);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int get = arrayQueue.headQueue();
System.out.printf("取出的头数据为:%d", get);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
default:
break;
}
}
System.out.println("程序已退出");
}
}
class ArrayQueue {
private final int maxSize;
private int front;
private int rear;
private int[] arr;
public ArrayQueue(int arrMaxSize) {
this.maxSize = arrMaxSize;
this.arr = new int[maxSize];
this.front = -1;
this.rear = -1;
}
public boolean isFull() {
return this.rear == this.maxSize - 1;
}
public boolean isEmpty() {
return this.rear == this.front;
}
public void addQueue(int data) {
if (this.isFull()) {
System.out.println("队列已满,无法添加新数据!");
return;
}
this.arr[++this.rear] = data;
}
public int getQueue() {
if (this.isEmpty()) {
throw new RuntimeException("队列为空,无法取出数据!");
}
return this.arr[++this.front];
}
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空!");
return;
}
for (int i = 0; i < this.arr.length; i++) {
System.out.printf("arr[%d]:%d\n", i, this.arr[i]);
}
}
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("数列为空!");
}
return this.arr[front + 1];
}
public int queueLen() {
return this.arr.length;
}
}
问题:
- 目前数组使用一次就无法使用,没有达到复用的效果。
- 将这个数组使用算法,改进成环形数组。核心
%
取模
数组模拟环形队列
思路如下:
- front变量的含义做一个调整:front指向队列的第一个元素,也就是说arr[front]就是队列的第一个元素。front 初始值 = 0
- rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置。因为希望空出一个空间作为约定。 rear 初始值 = 0
- 当队列满时,条件是:
(rear + 1) % maxSize = front
- 当队列为空时,条件是:
rear = front
- 队列中有效数据个数为
(rear + maxSize - front) % maxSize
代码实现:
package queue;
import java.util.Scanner;
public class CircleArrayQueueDemo {
public static void main(String[] args) {
CircleArrayQueue arrayQueue = new CircleArrayQueue(3);
char key = ' ';
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while (loop) {
System.out.println("s(show):显示队列");
System.out.println("e(quit):退出程序");
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 'e':
scanner.close();
loop = false;
break;
case 'a':
System.out.println("请输入一个数据:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case 'g':
try {
int get = arrayQueue.getQueue();
System.out.printf("取出的数据为:%d", get);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int get = arrayQueue.headQueue();
System.out.printf("取出的头数据为:%d", get);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
default:
break;
}
}
System.out.println("程序已退出");
}
}
class CircleArrayQueue {
private final int maxSize;
private int front;
private int rear;
private int[] arr;
public CircleArrayQueue(int arrMaxSize) {
this.maxSize = arrMaxSize;
this.arr = new int[maxSize];
}
public boolean isFull() {
return (this.rear + 1) % this.maxSize == this.front;
}
public boolean isEmpty() {
return this.rear == this.front;
}
public void addQueue(int data) {
if (this.isFull()) {
System.out.println("队列已满,无法添加新数据!");
return;
}
this.arr[this.rear] = data;
this.rear = (this.rear + 1) % this.maxSize;
}
public int getQueue() {
if (this.isEmpty()) {
throw new RuntimeException("队列为空,无法取出数据!");
}
int value = arr[this.front];
this.front = (this.front + 1) % this.maxSize;
return value;
}
public void showQueue() {
if (isEmpty()) {
System.out.println("队列为空!");
return;
}
for (int i = this.front; i < this.front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % this.maxSize, arr[i % this.maxSize]);
}
}
public int size() {
return (this.rear + this.maxSize - this.front) % this.maxSize;
}
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("数列为空!");
}
return this.arr[this.front];
}
public int queueLen() {
return this.arr.length;
}
}