一、队列
1.队列介绍
(1)队列是一个有序列表,可以用数组或是链表来实现。
(2)遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出。
(3)示意图:(使用数组模拟队列示意图)
2.数组模拟队列思路
(1)队列本省是有序列表,若使用数组的结构来存储队列的数据,则队列数组的声明如上图,其中maxSize是该队列的最大容量。
(2)因为队列的输出、输入是分别从前后端来处理,因此需要两个变量front及rear分别记录队列前后端的下标,front会随着数据输出而改变,而rear则是随着数据输入而改变,如上图。
(3)当我们将数据存入队列时称为“addQueue”,addQueue的处理需要两个步骤:思路分析
1.若尾指针rear小于队列的最大下表maxSize-1,则将数据存入rear所指的数组元素中,否则无法存入数据。rear == maxSize-1[队列满]
2.将尾指针往后移:rear+1。
(4)当我们将数据移除队列时称为“removeQueue” removeQueue的处理需要两个步骤:思路分析
1.若首指针小于尾指针,则将front所指的数据从数组中取出,否则无法取出数据。front == rear[队列空]
2.将首指针往后移:front+1。
(5)代码实现
public class ArrayQueue {
private int maxSize;//表示队列的最大容量
private int front;//首指针
private int rear;//尾指针
private int[] queue;//队列
public ArrayQueue(int maxSize){
this.maxSize = maxSize;
this.queue = new int[maxSize];
this.front = -1;//指向队列头部的前一个位置
this.rear = -1;//指向队列尾部
}
//判断队列是否满
public boolean isFull(){
return rear == maxSize-1;
}
//判断队列是否为空
public boolean isEmpty(){
return front == rear;
}
//入队列
public int addQueue(int value){
if (isFull()){
throw new RuntimeException("队列满,不能加入数据");
}
rear++;
queue[rear] = value;
return value;
}
//出队列
public int removeQueue(){
if (isEmpty()){
throw new RuntimeException("队列空,无法删除数据");
}
front++;
return queue[front];
}
//队列实际长度
public int size(){
return rear-front;
}
public void showQueue(){
if (isEmpty()){
throw new RuntimeException("队列空,没用4有数据");
}
for (int i = front+1; i <= rear; i++) {
System.out.println("queue["+i+"]="+queue[i]);
}
}
}
6)问题分析并优化
1.目前数据使用一次就不能用,没有达到复用的效果。
2.将这个数组使用算法,改进成一个环形的队列,取模:%。
3.数组模拟环形队列
对前面的数组模拟队列的优化,充分利用数组。因此将数组看组是一个环形的。(通过取模的方式来实现)
(1)分析说明:
1.尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定,这个在做判断队列满的时候需要注意(rear+1)%maxSize == front队列满
(2)rear == front[队列空]
(3)分析示意图:
(4)思路如下:
1.front变量的含义做一个调整:front就指向队列的第一个元素,也就是queue[front]就是对列的第一个元素,front的初始值=0
2.rear变量的含义做一个调整:rear指向队列的最后一个元素的后一个位置。因为希望空出一个空间做为约定,rear的初始值=0.
3.当队列满时,条件是(rear+1)%maxSize=front[队列满]。
4.当队列为空的条件,rear == front[队列空]
5.当我们这样分析,队列中有效的数据个数(rear+maxSize-front)%maxSize。
(5)代码实现
public class CircleQueue {
private int maxSize;//表示队列的最大容量
private int front;//首指针
private int rear;//尾指针
private int[] queue;//队列
public CircleQueue(int maxSize){
this.maxSize = maxSize;
this.queue = new int[maxSize];
this.front = 0;//指向队列头部
/*
*指向队列尾部的后一个位置,意思就是说如果maxSize=5,
*那这个队列最多能存储4个元素,因为要预留一个位置给尾指针
*/
this.rear = 0;
}
//判断队列是否满
public boolean isFull(){
return front == (rear+1)%maxSize;
}
//判断队列是否为空
public boolean isEmpty(){
return front == rear;
}
//入队列
public int addQueue(int value){
if (isFull()){
throw new RuntimeException("队列满,不能加入数据");
}
queue[rear] = value;
rear = (rear+1)%maxSize;
return value;
}
//出队列
public int removeQueue(){
if (isEmpty()){
throw new RuntimeException("队列空,无法删除数据");
}
int temp = queue[front];
front = (front+1)%maxSize;
return temp;
}
//显示队列的数据
public void showQueue(){
if (isEmpty()){
throw new RuntimeException("队列空,没用4有数据");
}
for (int i = front; i < front+size(); i++) {
System.out.println("queue["+i%maxSize+"]="+queue[i%maxSize]);
}
}
//得到队列数据有效个数
public int size(){
return (rear+maxSize-front)%maxSize;
}
}