概述
队列是一个有序列表,可以用数组或是链表来实现。
遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
示意图:(使用数组模拟队列示意图)
- 队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如下图, 其中 maxSize 是该队列的最大容量。
- 因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 front及 rear分别记录队列前后端的下标,front会随着数据输出而改变,而 rear则是随着数据输入而改变
数组模拟队列
当我们将数据存入队列时称为”addQueue”,addQueue 的处理需要有两个步骤:
思路分析
将尾指针往后移:rear+1 , 当front == rear 【空】
若尾指针 rear 小于队列的最大下标 maxSize-1,则将数据存入 rear所指的数组元素中,否则无法存入数据。 rear == maxSize - 1[队列满]
入队操作addQueue
出队列操作getQueue
显示队列的情况showQueue
查看队列头元素headQueue
退出系统exit
只有在出队入队的时候才会改变rear和front,这种队列的问题是当数据存满后,即使将所有元素出队,也不能再次入队。
package com.m.demo2;
public class arrayQueue {
private int front;
private int rear;
private int maxsize;
private int array[];
// 构造函数
public arrayQueue(int maxsize) {
this.maxsize = maxsize;
front = -1;
rear = -1;
array = new int[maxsize];
}
// 入队操作addQueue
public void addQueue(int a) {
// 判断是否满了
if (rear >= maxsize - 1) {
throw new RuntimeException("队列满了");
}
rear++;
array[rear] = a;
}
// 出队列操作getQueue
public int getQueue() {
if (rear == front) {
throw new RuntimeException("队列空了");
}
front++;
return array[front];
}
//显示队列的情况showQueue
public void showQueue() {
for (int i = front+1; i < maxsize; i++) {
System.out.printf("array[%d]=%d\n", i, array[i]);
}
}
// 查看队列头元素headQueue
public void headQueue() {
int i=front+1;
System.out.printf("array[%d]=%d\n", i, array[i]);
}
}
package com.m.demo2;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// 构建队列
arrayQueue aq = new arrayQueue(3);
boolean flag = true;
int ch = -1;
Scanner sc = new Scanner(System.in);
while (flag) {
System.out.println("0:退出");
System.out.println("1:入队");
System.out.println("2:出队");
System.out.println("3:显示队列");
System.out.println("4:显示对头");
System.out.println("请输入操作项");
ch = sc.nextInt();
switch (ch) {
case 0:
flag = false;
break;
case 1:
System.out.println("请输入添加的数字");
int a = sc.nextInt();
aq.addQueue(a);
break;
case 2:
System.out.println(aq.getQueue());
break;
case 3:
aq.showQueue();
break;
case 4:
aq.headQueue();
break;
default:
throw new RuntimeException("输入错误,请重输");
}
}
System.out.println("退出");
}
}
数组模拟环形队列
对前面的数组模拟队列的优化,充分利用数组. 因此将数组看做是一个环形的。(通过取模的方式来实现即可)
分析说明:
尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意 (rear + 1) % maxSize == front 【满]】
rear == front 【空】
思路如下:
1. front 变量的含义做一个调整: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素
front 的初始值 = 0
2. rear 变量的含义做一个调整:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.
rear 的初始值 = 0
3. 当队列满时,条件是 (rear + 1) % maxSize == front 【满】
4. 对队列为空的条件, rear == front 空
5. 当我们这样分析, 队列中有效的数据的个数 (rear + maxSize - front) % maxSize
// rear = 1 front = 0
6. 我们就可以在原来的队列上修改得到,一个环形队列
注意问题:if 里面需要及时返回,rear front 需要及时限制范围
package com.m.demo3;
public class circleQueue {
private int front;
private int rear;
private int maxsize;
private int array[];
// 构造函数
public circleQueue(int maxsize) {
this.maxsize = maxsize;
array = new int[maxsize];
}
// 入队操作addQueue
public void addQueue(int a) {
// 判断是否满了
if ((rear+1)%maxsize==front) {
System.out.println("队列满了");
}else {
array[rear] = a;
rear=(rear+1)%maxsize;
}
}
// 出队列操作getQueue
public int getQueue() {
if (rear == front) {
System.out.println("队列空了");
return -1;
}else {
int a=array[front];
front=(front+1)%maxsize;
return a;
}
}
//有效元素
public int size() {
// System.out.println("rear="+rear);
// System.out.println("front="+front);
// System.out.println("maxsize"+maxsize);
return (rear-front+maxsize)%maxsize;//需要+maxsize是因为rear有可能会比front小
}
//显示队列的情况showQueue
public void showQueue() {
for (int i = front; i < front+size(); i++) {
System.out.printf("array[%d]=%d\n", i%maxsize, array[i%maxsize]);
}
}
// 查看队列头元素headQueue
public void headQueue() {
int i=front%maxsize;
System.out.printf("array[%d]=%d\n", i, array[i]);
}
}
package com.m.demo3;
import java.util.Scanner;
import com.m.demo2.arrayQueue;
public class Test {
public static void main(String[] args) {
// 构建队列
circleQueue cq = new circleQueue(3);
boolean flag = true;
int ch = -1;
Scanner sc = new Scanner(System.in);
while (flag) {
System.out.println("0:退出");
System.out.println("1:入队");
System.out.println("2:出队");
System.out.println("3:显示队列");
System.out.println("4:显示对头");
System.out.println("5:元素个数");
System.out.println("请输入操作项");
ch = sc.nextInt();
switch (ch) {
case 0:
flag = false;
break;
case 1:
System.out.println("请输入添加的数字");
int a = sc.nextInt();
cq.addQueue(a);
break;
case 2:
System.out.println(cq.getQueue());
break;
case 3:
cq.showQueue();
break;
case 4:
cq.headQueue();
break;
case 5:
System.out.println(cq.size());
break;
default:
System.out.println("输错了");
}
}
System.out.println("退出");
}
}