介绍:
队列是一个有序列表,可以用数组或是链表来实现。
遵循先入先出的原则。
示意图:
maxSize:该队列的最大容量。
front、rear:分别记录队列前后端的下标。
front是队列最前元素(不含),rear队列最后元素(含)。
front会随着数据输出而改变,而rear则是随着数据输入而改变。
一、数组实现队列
注意点:这是一次性的,存满后,全部取出后不能再进行添加,后面实现循环队列解决
1.1 思路
-
添加:
1)将尾指针往后移=> rear+1,当front== rear 【队列空】。
2)若尾指针rear小于队列的最大下标maxSize-1,则将数据存入rear所指的数组元素中;否则无法存入数据,rear== maxSize-1【队列满】。 -
取出队列头数据
1)返回一个值,判断队列是否为空。
为空,则throw new RuntimeException("为空 ");
不为空,则front++,return arr[front]。 -
显示队列中所有数据
1)判断队列是否为空。
为空,则System.out.println("为空 ");
不为空,遍历数组,输出数据。 -
显示队列头数据
1)返回一个值,判断队列是否为空。
为空,则throw new RuntimeException("为空 ");
不为空,则,return arr[front+1]。
1.2 具体代码
public class ArrayQueueDemo {
public static void main(String[] args)
{
//arrMaxSize
int arrMaxSize = 3;
ArrayQueue arrayQueue = new ArrayQueue(arrMaxSize);
char key=' '; //接受用户输入
Scanner sc = new Scanner(System.in);
boolean flag=true;
while(flag) {
System.out.println("------数组模拟队列--------");
System.out.println("s(showAll):显示队列");
System.out.println("a(add):添加数据到队列");
System.out.println("g(getHead):获取队列头部的数据");
System.out.println("f(front):显示队列头部的数据");
System.out.println("e(exit):退出");
System.out.println("请选择:");
key=sc.nextLine().charAt(0); //获取第一个字符
switch (key) {
case 's':
arrayQueue.showAll();
break;
case 'a':
try {
System.out.println("请输入一个数字:");
int num=sc.nextInt();
arrayQueue.add(num);
} catch (InputMismatchException e1) {
System.out.println("输入错误!");
}
sc.nextLine();
break;
case 'g':
try {
int res=arrayQueue.get();
System.out.println("取出的数据是:"+res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'f':
try {
int res=arrayQueue.showHead();
System.out.println("front的数据是:"+res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
sc.close();
flag=false;
break;
default:
break;
}
}
System.out.println("程序退出!");
}
}
//使用一个数组模拟队列==编写一个ArrayQueue类
class ArrayQueue{
private int maxSize; //表示数组的最大容量
private int front; //队列头
private int rear; //队列尾
private int [] arr; //定义一个数组 用于存放数据
//创建队列的构造器
public ArrayQueue(int arrMaxSize) {
maxSize=arrMaxSize;
arr=new int [maxSize];
front=-1; //指向队列头部,分析出front是指向队列头的前一个位置
rear=-1; //指向队列尾,指向队列尾的数据(即包含队列最后一个数据)
}
//判断队列是否满
public boolean isFull() {
return rear==maxSize-1;
}
//判断队列是否为空
public boolean isEmpty() {
return rear==front;
}
//向队列添加数据
public void add(int num) {
if(isFull()) {
System.out.println("队列已经满了");
return;
}
//尾部加一
rear++;
arr[rear]=num;
System.out.println("数据添加成功!");
}
//获取队列数据
public int get() {
if(isEmpty()) {
throw new RuntimeException("该队列为空,暂无数据!");
}
front++;
return arr[front];
}
//显示队列中所有的数据
public void showAll() {
if(isEmpty()) {
System.out.println("该队列为空,暂无数据!");
return;
}
//遍历
for (int i = 0; i < arr.length; i++) {
System.out.println("arr["+i+"]="+arr[i]);
}
}
//查看给队列的头部的数据值
public int showHead() {
if(isEmpty()) {
throw new RuntimeException("该队列为空,暂无数据!");
}
return arr[front+1];
}
}
二、数组实现循环队列
2.1 思路
- front:指向队列的第一个元素,arr[front]是队列的第一个元素,front=0。
- rear:指向队列的最后一个元素的后一个位置,希望空出一个空间做约定,rear=0。
- 当队列满时:(rear+1)%maxSize==front【队列满】
- 当队列为空时:rear==front【队列空】
- 队列中有效的数据个数:(rear-front+maxSize)%maxSize
- 再在上面的实现队列中进行修改。
2.2 具体代码
public class CircleQueueDemo {
public static void main(String[] args) {
int ArrMaxSize=4;
CircleQueue CircleQueue=new CircleQueue(ArrMaxSize);
char key = ' '; // 接受用户输入
Scanner sc = new Scanner(System.in);
boolean flag = true;
while (flag) {
System.out.println("------数组模拟队列--------");
System.out.println("s(showAll):显示队列");
System.out.println("a(add):添加数据到队列");
System.out.println("g(getHead):获取队列头部的数据");
System.out.println("f(front):显示队列头部的数据");
System.out.println("e(exit):退出");
System.out.println("请选择:");
key = sc.nextLine().charAt(0); // 获取第一个字符
switch (key) {
case 's':
CircleQueue.showAll();
break;
case 'a':
try {
System.out.println("请输入一个数字:");
int num = sc.nextInt();
CircleQueue.add(num);
} catch (InputMismatchException e1) {
// TODO Auto-generated catch block
System.out.println("输入错误!");
}
sc.nextLine();
break;
case 'g':
try {
int res = CircleQueue.get();
System.out.println("取出的数据是:" + res);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage());
}
break;
case 'f':
CircleQueue.showHead();
break;
case 'e':
sc.close();
flag = false;
break;
default:
break;
}
}
System.out.println("程序退出!");
}
}
class CircleQueue {
private int maxSize; // 表示数组的最大容量
private int front; // 指向队列第一个元素的位置,初始值为0
private int rear; // 指向队列最后一个元素的下一个位置,初始值为0
private int[] array; // 定义数组用于存放数据
// 构造器
public CircleQueue(int ArrMaxSize) {
maxSize = ArrMaxSize;
array = new int[maxSize];
}
// 判断队列是否已满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
// 判断队列是否为空
public boolean isEmpty() {
return rear == front;
}
// 添加数据到队列
public void add(int num) {
// 先判断队列是否已经满了
if (isFull()) {
System.out.println("队列已经满了,无法添加数据!");
return;
}
array[rear] = num;
System.out.println("数据添加成功!");
// 这里必须考虑取余
rear = (rear + 1) % maxSize;
}
// 取出队列的第一个数据
public int get() {
if (isEmpty()) {
throw new RuntimeException("该队列为空,暂无数据!");
}
int num = array[front];
// 必须考虑取余
front = (front + 1) % maxSize;
return num;
}
// 获取循环队列中的有效数据的个数
public int count() {
return (rear + maxSize - front) % maxSize;
}
// 查询所有的队列
public void showAll() {
// 判断队列是否为空
if (isEmpty()) {
System.out.println("队列为空!");
return;
}
// 从front开始遍历,有效个数为count()个
for (int i = front; i < front + count(); i++) {
System.out.println("array[" + i % maxSize + "]=" + array[i % maxSize]);
}
}
// 显示循环队列中的第一个元素值
public void showHead() {
// 判断队列是否为空
if (isEmpty()) {
System.out.println("队列为空!");
return;
}
System.out.println("队列的第一个元素值为:" + array[front]);
}
}