队列
队列是一个有序列表,可能用数组或链表来实现。
先进入的数据先取出,后进入的数组后取出。
数组模拟队列的思路:
队列本身就是一个有序列表,maxSize来记录该数组最大容量;front和rear分别记录队列前后端的下标,front随着数据输出而改变,rear随着数据输入而改变。
加入数据:若队列不为满,尾部指针后移:rear+1
拿出数据:若队列不为空,前端指针后移:front+1
代码:
package com.dataStructure;
import java.util.Scanner;
public class arrayQueue {
public static void main(String[] args) {
Queue arrayQueue = new Queue(3);
String key = "";
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while (loop) {
//输出一个菜单
System.out.println("press s to show Queue");
System.out.println("press e to exit program");
System.out.println("press a to add element");
System.out.println("press g to get data");
key = scanner.next();
switch (key) {
case "s":
arrayQueue.showQueue();
break;
case "e":
scanner.close();
loop = false;
break;
case"a":
System.out.println("Input a word:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case"g":
System.out.println(arrayQueue.getQueue());
break;
}
}
}
}
class Queue {
//装入👴需要的私有变量
private int rear = -1;
private int front = -1;
private int maxSize;
private int[] que;
//设置Queue的规格
public Queue(int size) {
maxSize = size;
que = new int[size];
}
//判断Queue是否为空
public boolean isEmpty() {
return rear == front;
}
//判断Queue满了没
public boolean isFull() {
return rear == maxSize - 1;
}
//加入一个新元素
public void addQueue(int n) {
if (isFull()) {
System.out.println("Queue is full! can not add!");
return;
}
rear++;
que[rear] = n;
}
//删除一个元素
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("Queue is empty! can not delete!");
}
front++;
return que[front];
}
//showQueue
public void showQueue() {
if (isEmpty()) {
System.out.println("队列空,无数据,无法showQueue");
} else {
for (int i = 0; i < que.length; i++) {
System.out.printf("Queue[%d] = %d\n", i, que[i]);
}
}
}
}
这时候存在一个问题,数组使用一次之后就不能用了,没有达到复用的效果,例如,我将位置填满后再全部删去,这时候我就没办法再add新的元素进去了。
使用数组模拟形成一个环形队列,利用取模的方式实现。
使用数组模拟环形队列
思路:
1. Front作为队列第一个元素的引用,初始front = 0
2. Rear作为队列最后一个元素的后一个元素的引用,初始rear = 0
3. 队列满时,条件为(rear+1)%maxSize = front。
这里要注意的是,虽然maxSize是5,但是我们实际可以使用的只有4个。当总共有5个格子时,分别为0,1,2,3,4,满了的时候,rear = 4,front = 0,maxSize = 5;带入公示4+1模除5 = front = 0。
4. 队列空时,rear = front。
当rear-1=front时,实际上只有一个元素,就是front所在的位置;当rear = front的时候,最后一个元素rear-1在最初的元素front之前,所以这种情况不存在。
5. 队列中有效数字的个数为(rear-front+maxSize)% maxSize。
综合4来理解,rear-1 = front时候,存在一个元素,rear = front的时候,不存在元素,maxSize%maxSize永远为0,所以很显然(rear-front)% maxSize就是存在有效数字的个数。这里一定要加maxSize再取模,因为rear-front可能是负数,所以必加。
代码:
package com.dataStructure;
import java.util.Scanner;
public class arrayCircleQueue {
public static void main(String[] args) {
CircleQueue arrayQueue = new CircleQueue(4);
String key = "";
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while (loop) {
//输出一个菜单
System.out.println("press s to show Queue");
System.out.println("press e to exit program");
System.out.println("press a to add element");
System.out.println("press g to get data");
key = scanner.next();
switch (key) {
case "s":
arrayQueue.showQueue();
break;
case "e":
scanner.close();
loop = false;
break;
case"a":
System.out.println("Input a word:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
case"g":
System.out.println(arrayQueue.getQueue());
break;
}
}
}
}
class CircleQueue {
//装入👴需要的私有变量
private int rear = 0;
private int front = 0;
private int maxSize;
private int[] que;
//设置Queue的规格
public CircleQueue(int size) {
maxSize = size;
que = new int[size];
}
//判断Queue是否为空
public boolean isEmpty() {
return rear == front;
}
//判断Queue满了没
public boolean isFull() {
return (rear+1)%maxSize == front;
}
//加入一个新元素
public void addQueue(int n) {
if (isFull()) {
System.out.println("Queue is full! can not add!");
return;
}
que[rear] = n;
rear = (rear+1)%maxSize;
}
//删除一个元素
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("Queue is empty! can not delete!");
}
int value = que[front];
front = (front+1)%maxSize;
return value;
}
//showQueue
public void showQueue() {
if (isEmpty()) {
System.out.println("队列空,无数据,无法showQueue");
} else {
for (int i = front; i < front+(rear+maxSize-front)%maxSize; i++) {
System.out.printf("Queue[%d] = %d\n", i%maxSize, que[i%maxSize]);
}
}
}
}