队列是一个有序链表,可以用数组或是链表来实现
遵循先入先出原则。即:先存入队列的数据,要先取出。后存入的要后取出
数组模拟队列
1.顺序队列
示意图:(使用数组模拟队列示意图)
- front是头部,rear尾部。存入数据时候尾部移动,头部不动。取出数据时候尾部不动,头部移动。
- front随着数据输出而变化,rear随着数据输入而变化。
- front指向队列头部,front指向的是队列头数据的前一个位置(即不是队列的第一个数据)。rear指向队列尾,指向队列尾的数据(即就是队列最后一个数据)
代码实现:
package com.icon.QueueTest;
import jdk.internal.org.objectweb.asm.tree.IntInsnNode;
import java.util.Queue;
import java.util.Scanner;
/**
* ClassName: ArrayQueueDemo
* Description:数组模拟顺序队列
* date: 2021/2/16 11:49
*
* @author:icon
* @version:
* @since JDK 1.8
*/
public class ArrayQueueDemo {
public static void main(String[] args) {
ArrayQueue queue = 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':
try {
queue.getAllDate();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'a':
System.out.println("请输入您想要添加的数据");
int n = scanner.nextInt();
try {
queue.addDate(n);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'g':
try {
int res = queue.getFront();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
queue.headQueue();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
}
}
System.out.println("程序退出~~");
}
}
class ArrayQueue {
private int maxSize;//队列最大容纳的值
private int front;//指向队列的头部
private int rear;//指向队列的尾部的后一个元素
private int[] queue;//数组模拟队列
public ArrayQueue(int maxSize) {
this.maxSize = maxSize;
this.front = 0;
this.rear = 0;
this.queue = new int[maxSize];
}
//判断队列是否空值
public boolean isEmpty() {
return rear == front;
}
//判断队列是否已满
public boolean isFull() {
return rear == maxSize-1;
}
//向队列中添加数据
public void addDate(int n) {
if (isFull()) {
throw new RuntimeException("队列已满,无法添加");
}else{
rear++;
queue[rear] = n;
}
}
// 获取队列的数据, 出队列
public int getFront() {
if (isEmpty()) {
throw new RuntimeException("当前队列为空");
} else {
front++;
return queue[front];
}
}
//获取队列所有数据
public int getAllDate() {
if (isEmpty()) {
throw new RuntimeException("此时队列为空");
} else {
for (int i = 0; i < queue.length; i++) {
System.out.printf("arr[%d]=%d\n", i, queue[i]);
}
}
return 0;
}
//获取队列的头数据
public int headQueue() {
if (isEmpty()) {
throw new RuntimeException("数组为空");
} else {
return queue[front + 1];
}
}
}
问题分析并优化:
1)目前数组使用一次就不能用,没有达到复用的效果
2)将这个数组使用算法,改进成一个环形的数组(利用取模%)
2.环形队列
思路如下:
- front变量的含义进行调整:front就指向队列的第一个元素,也就是说arr[front] 就是队列的第一个元素
- rear变量的含义进行调整:rear指向队列的最后一个元素的后一个位置,因为希望空出一个空间作为约定,rear的初始值=0
- 当队列满时,条件是(rear+1)%maxSize==front【满】
- 当队列为空时,条件是 rear == front【空】
- 此时,队列中的有效数据个数为 (rear+maxSize-front)%maxSize
- 这是,我们在原来队列的基础上,得到一个环形队列
示意图:
代码实现:
package com.icon.QueueTest;
import java.util.Scanner;
/**
* ClassName: CircleArrayQueueDemo
* Description:数组模拟循环队列(空出一位法)
* date: 2021/2/16 14:51
*
* @author:icon
* @version:
* @since JDK 1.8
*/
public class CircleArrayQueueDemo {
public static void main(String[] args) {
CircleArrayQueue queue = new CircleArrayQueue(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':
try {
queue.getAllDate();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'a':
System.out.println("输出一个数");
int value = scanner.nextInt();
queue.addDate(value);
break;
case 'g':
try {
int res = queue.getDate();
System.out.printf("取出的数据是%d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
queue.HeadDate();
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
}
}
System.out.println("程序退出~~");
}
}
class CircleArrayQueue {
private int maxSize;//队列最大容纳的值
private int front;//指向队列的头部
private int rear;//指向队列的尾部的后一个元素
private int[] queue;//数组模拟队列
public CircleArrayQueue(int maxSize) {
this.maxSize = maxSize;
queue=new int[maxSize];
}
//判断队列是否已满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
// 添加数据到队列
public void addDate(int n) {
if (isFull()) {
System.out.println("队列满,不能加入数据~");
return;
}
//直接将数据加入
queue[rear] = n;
//将 rear 后移, 这里必须考虑取模
rear = (rear + 1) % maxSize;
}
// 获取队列的数据, 出队列
public int getDate() {
if (isEmpty()) {
throw new RuntimeException("此时队列没有数值");
} else {
int value = queue[front];
front = (front + 1) % maxSize;
return value;
}
}
//显示队列的所有元素
public void getAllDate() {
if (isEmpty()) {
throw new RuntimeException("当前队列为空值");
} else {
for (int i = front; i < front+getSize(); i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, queue[i % maxSize]);
}
}
}
//获取当前对类的有效元素个数
public int getSize() {
return (rear + maxSize - front) % maxSize;
}
// 显示队列的头数据, 注意不是取出数据
public int HeadDate() {
if (isEmpty()) {
throw new RuntimeException("队列空的,没有数据~~");
} else
return queue[front];
}
}
未完…