队列介绍
队列是一个有序列表,可以用数组或是链表来实现
遵循先入后出的原则。及先存入队列的数据,要先取出。后存入的要后取出
使用数组模拟队列示意图:
数组模拟队列
队列本身是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如上图,其中maxSize是该队列的最大容量。
因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变,如上图所示。
向队列存放数据
当我们将数据存入队列时称为“ addQueue" , addQueue 的处理需要有两个步骤:
1.将尾指针往后移:rear + 1 ,当front == rear 【队列空】
2.若尾指针rear小于队列的最大下标maxSize - 1,则将数据存入rear所指的数组元素中,否则无法存入数据。rear == maxSize - 1 【队列满】
(rear 是队列最后[含] front是队列最前元素[不含])
代码如下:
public class ArrayQueueTest {
public static void main(String[] args) {
ArrayQueue queue = new ArrayQueue(7);
queue.addQueue(15);
queue.addQueue(8);
queue.addQueue(3);
queue.addQueue(19);
queue.addQueue(13);
queue.addQueue(7);
queue.addQueue(9);
//显示队列里的数据
System.out.println("显示队列里的数据:");
queue.showQueue();
System.out.println("出队列的值:" + queue.getQueue());
System.out.println("出队列后:");
queue.showQueue();
System.out.println("看一眼头队列的数据:" + queue.queueHead());
}
}
class ArrayQueue{
private int front;//表示队列头
private int rear;//表示队列尾
private int maxSize;//表示数组的最大容量
private int[] arr;//用数组模拟队列
//创造队列的构造器,front/rear的默认值为 -1
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
front = -1;
rear = -1;
arr = new int[maxSize];
}
//判断队列是否满
public boolean isFull() {
return rear == maxSize - 1;
}
//判断队列是否空
public boolean isEmpty() {
return front == rear;
}
//添加数据到数组
public void addQueue(int data) {
if(isFull()) {
System.out.println("队列满了,不能添加数据!");
return;
}
rear++;//让rear后移
arr[rear] = data;
}
//出队列,并返回队列的数据
public int getQueue() {
if(isEmpty()) {
return -1;
}
front++;
return arr[front];
}
//显示队列的所有数据
public void showQueue() {
for(int i = front + 1;i <= rear;i++) {
System.out.println(arr[i]);
}
}
//显示队列的头数据,不是出队列,只是看一眼
public int queueHead() {
if(isEmpty()) {
throw new RuntimeException("队列为空,没有数据");
}
return arr[front + 1];
}
}
数组模拟环形队列
对前面的数组模拟队列的优化,充分利用数组。因此将数组看做是一个环形的。(通过取模的方式来实现即可)
分析说明:
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
代码如下:
public class CircleQueueTest {
public static void main(String[] args) {
CircleQueue queue = new CircleQueue(7);
queue.addQueue(15);
queue.addQueue(8);
queue.addQueue(3);
queue.addQueue(19);
queue.addQueue(13);
queue.addQueue(7);
System.out.println("显示队列的数据:");
queue.printQueue();;
System.out.println("出队列的值:" + queue.getQueue());
System.out.println("出队列后:");
queue.printQueue();
System.out.println("队列里有多少个值:" + queue.getSum());
}
}
class CircleQueue{
private int front;//表示队列头
private int rear;//表示队列尾
private int maxSize;//表示队列的最大容量
private int[] arr;//用数组模拟队列
//构造器,头节点和尾节点的初始值尾0
public CircleQueue(int arrMaxSize){
front = 0;
rear = 0;
maxSize = arrMaxSize;
arr = new int[maxSize];
}
//判断队列是否满
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
//判断队列是否空
public boolean isEmpty() {
return front == rear;
}
//向队列里添加数据
public void addQueue(int data) {
if(isFull()) {
System.out.println("该队列已经满了,不能添加数据");
return;
}
if(rear == maxSize - 1) {
arr[rear] = data;
rear -= maxSize - 1;
}else {
arr[rear] = data;
rear++;
}
}
//出队列,并返回数据
public int getQueue() {
if(isEmpty()) {
System.out.println("该队列为空,没有数据出队列");
return -1;
}
if(front == maxSize - 1) {
int data = arr[front];
front -= maxSize - 1;
return data;
}else {
return arr[front++];
}
}
//显示队列的所有数据
public void printQueue() {
if(isEmpty()) {
System.out.println("该队列为空,没有数据显示");
return;
}
for(int i = front;i < rear;i++) {
System.out.println(arr[i]);
}
}
//返回队列里的有效的数据个数
public int getSum() {
return (rear + maxSize -front) % maxSize;
}
}