1 队列
队列是一个有序的列表,可以使用数组或者链表来实现,遵循先入先出的原则。即先存入数据先去取出来,后存入数据后取出来
2 数组模拟队列
2.1思路分析
1)队列存在最大容量使用maxSize来表示,存在输入和输出,分别使用front和rear来记录前后端下标。
2)当有数据输出是front会发生移动,当有数据输入的时候rear也会发生移动
demo1:缺陷版数组模拟队列
缺陷:数组无法复用,当队列满了之后,即便是取出数据也无法再次添加数据
实现:
1)添加数据时:rear+1
2)输出数据时:front+1
3)front=rear时为空
4)rear==maxSize-1(队列满了)
5)初始值front=rear=-1;
6)front指向队列首的前一个,rear指向队列中的最后一个数据。
代码
/**
* 使用数组模拟队列:此时为非环形队列,即存在一个问题,数组只能使用一个,即不可复用。
*
* @author 龍
*/
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(exit):退出程序");
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 res = arrayQueue.getQueue();
System.out.println("取出的数据为:" + res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
//查看队列头的数据
case 'h':
try {
int res = arrayQueue.headQueue();
System.out.println("队列头的数据为:" + res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
default:
System.out.println("输入代码无效!!!");
break;
}
}
System.out.println("程序退出");
}
}
/**
* 编写一个ArrayQueue类
*/
class ArrayQueue {
/**
* 队列最大容量
*/
private int maxSize;
/**
* 队列头
*/
private int front;
/**
* 队列尾
*/
private int rear;
/**
* 数组用来存放数据,模拟队列
*/
private int[] arr;
/**
* 创建队列构造器
*/
ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
//指向队列头部-->指向队列头的前一个位置
front = -1;
//执行队列尾部,指向队列尾的数据(即队列尾的最后一个数据)
rear = -1;
}
/**
* 判断队列是否满
*/
private boolean isFull() {
return rear == maxSize - 1;
}
/**
* 判断队列是否为空
*/
private boolean isEmpty() {
return rear == front;
}
/**
* 添加数据队列
*/
void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列已满,不能加入数据!!!");
return;
}
//让rear后移
rear++;
//赋值
arr[rear] = n;
}
/**
* 获取队列的数据,出队列
*/
int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列是空的,无法取出数据!!!");
}
front++; //使得后移
return arr[front];
}
/**
* 展示当前队列的所有数据
*/
void showQueue() {
//遍历
if (isEmpty()) {
System.out.println("队列是空的,没有数据!!!");
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.println("array[" + i + "]" + " = " + arr[i]);
}
}
/**
* 显示队列的头数据,不是取数据
*/
int headQueue() {
//判断
if (isEmpty()) {
throw new RuntimeException("队列是空的,无法取出数据!!!");
}
return arr[front + 1];
}
}
改进的方法:使用环形数组来实现数组的复用
分析:
1)队列满的条件:(rear+1)%maxSizefront。
2)队列为空的条件:rearront。
3)有效数据的个数:(rear+maxSize-front)%maxSize
注意:
front和rear的含义发生了变化----->
front:指向队列首的第一个数据
rear:指向队列队尾的最后一个数据的后一个位置。
代码实现
/**
* @author 龍
* 环形数组实现队列
*/
public class CircleArrayQueueDemo {
public static void main(String[] args) {
System.out.println("测试环形数组模拟队列S");
CircleQueue circleQueue = new CircleQueue(4);
char key = ' ';
Scanner scanner = new Scanner(System.in);
boolean loop = true;
while (loop) {
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列取出数据");
System.out.println("h(head): 查看队列头的数据");
//接收一个字符
key = scanner.next().charAt(0);
switch (key) {
case 's':
circleQueue.showQueue();
break;
//退出
case 'e':
scanner.close();
loop = false;
break;
case 'a':
System.out.println("输出一个数");
int value = scanner.nextInt();
circleQueue.addQueue(value);
break;
//取出数据
case 'g':
try {
int res = circleQueue.getQueue();
System.out.println("取出的数据为:" + res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
//查看队列头的数据
case 'h':
try {
int res = circleQueue.headQueue();
System.out.println("队列头的数据为:" + res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
default:
System.out.println("输入指令错误!!!");
}
}
System.out.println("程序退出");
}
}
/**
* @author long
*/
class CircleQueue {
/**
* 队列最大容量
*/
private int maxSize;
/**
* 变量的含义进行了一个小调整,front指向队列的第一个元素,即array【front】,初始值为0.
*/
private int front;
/**
* 指向队列的最后一个元素的后一个位,因此希望空出一个位置。初始值为0。
*/
private int rear;
/**
* 数组用来存放数据,模拟队列
*/
private int[] arr;
/**
* 创建队列构造器
*/
public CircleQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
//指向队列头部-->指向队列头的前一个位置(默认为0,可以不写)
front = 0;
//执行队列尾部,指向队列尾的数据(即队列尾的最后一个数据)
rear = 0;
}
/**
* 判断队列是否满
*/
public boolean isFull() {
return front == ((rear + 1) % maxSize);
}
/**
* 判断队列是否为空
*/
public boolean isEmpty() {
return rear == front;
}
/**
* 添加数据队列
*/
public void addQueue(int n) {
//判断队列是否满
if (isFull()) {
System.out.println("队列已满,不能加入数据!!!");
return;
}
//赋值
arr[rear] = n;
//让rear后移,必须考虑取模
rear = (rear + 1) % maxSize;
}
/**
* 获取队列的数据,出队列
*/
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列是空的,无法取出数据!!!");
}
//front指向队列的第一个元素
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
/**
* 展示当前队列的所有数据
*/
public void showQueue() {
//遍历
if (isEmpty()) {
System.out.println("队列是空的,没有数据!!!");
return;
}
//需要考虑数据的顺序,从front开始遍历
for (int i = front; i < front + getSize(); i++) {
System.out.println("array[" + i % maxSize + "]" + " = " + arr[i % maxSize]);
}
}
/**
* 显示队列的头数据,不是取数据
*/
public int headQueue() {
//判断
if (isEmpty()) {
throw new RuntimeException("队列是空的,无法取出数据!!!");
}
return arr[front];
}
/**
* 求出当前队列的有效数据的个数
*/
public int getSize() {
return (rear + maxSize - front) % maxSize;
}
}
未完待续…