队列
- 队列是一个有序列表,可以用数组或是链表来实现。
- 遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
用数组模拟队列示意图
maxSize:数组的长度
rear:指向队列的最后一个元素的后一个位置
front:指向队列中第一个元素的位置
顺序队列
当队列中元素为空时
向队列中添加元素时
将元素添加到rear指向的位置中,再将rear后移一位
向队列中取出元素时
将当前front指向的位置中的元素取出,再将front后移一位
1.当rear == front时,队列为空,不可取出数据
2.当rear == maxSize时,队列已满,不可添加数据
代码实现
class Queue{
//队列的最大容量
private int maxSize;
//队列的头部
private int front = 0;
//队列尾部的后一个位置
private int rear = 0;
//模拟队列的数组
private int[] arr;
//初始化
public Queue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
}
//判断是否为空
public boolean isNull(){
return front == rear;
}
//判断是否已满
public boolean isFull(){
return rear == maxSize;
}
//添加
public void add(int x){
if (isFull()){
System.out.println("队列满,无法添加~~");
return;
}
//将元素添加到当前rear指向的位置,并将rear后移一位
arr[rear++] = x;
}
//取出
public int get(){
if (isNull())
throw new RuntimeException("队列空,无法取出~~");
//将当前front指向的位置上的元素取出,并将front后移
return arr[front++];
}
//查看队列中的元素
public void show(){
for (int i = front; i < rear; i++){
System.out.print(arr[i]+" ");
}
System.out.println();
}
public void showFirst(){
if (isNull()){
System.out.println("队列空,无下一个取出元素~~");
}
System.out.println(arr[front]);
}
}
顺序队列的缺点
在上图中我们的队列最大容量为6,也就是说,只要没有取出元素数量(有效元素数量)没有超过该值时,我们就可以继续添加,但事实上,我们在添加到队列满,然后取出元素后,仍然无法继续添加,原因在于我们元素被取出后的空间
无法继续利用,导致“假溢出”。为了解决这一问题,环形队列由此诞生。
环形队列
环形队列中解决“假溢出”的方法
当添加元素后,队列已满时,会将rear指针指向数组的第一个位置
添加元素时
与顺序队列相同,但为了保证rear永远小于maxSize,在rear后移一位后再与maxSize进取模运算
取出元素时
与顺序队列相同,但为了保证front永远小于maxSize,在front后移一位后再与maxSize进取模运算
但这里又有了新的问题,我们无法通过front == rear来判断当前为空
队列为空时
队列已满时
此时我们需要空出一个位置作为“约定”
也就是说,只要队列中还剩一个位置时,此时的队列已满
判断队列已满:(rear+1) %maxSize == front
判断队列为空:rear == front
计算队列中有效元素数量:(rear - front + maxSize) % maxSize
代码实现
class Queue{
//队列的最大容量
private int maxSize;
//队列的头部
private int front = 0;
//队列尾部的后一个位置
private int rear = 0;
//模拟队列的数组
private int[] arr;
//初始化
public Queue(int maxSize) {
this.maxSize = maxSize;
arr = new int[maxSize];
}
//判断是否为空
public boolean isNull(){
return front == rear;
}
//判断是否已满
public boolean isFull(){
return (rear + 1) % maxSize == front;
}
//添加
public void add(int x){
if (isFull()){
System.out.println("队列满,无法添加~~");
return;
}
//将元素添加到当前rear指向的位置,并将rear后移一位
arr[rear] = x;
rear = (rear + 1) % maxSize;
}
//取出
public int get(){
if (isNull())
throw new RuntimeException("队列空,无法取出~~");
//将当前front指向的位置上的元素取出,并将front后移
int x = arr[front];
front = (front + 1) %maxSize;
return x;
}
//查看队列中的元素
public void show(){
for (int i = front; i < front + effectiveQuantity(); i++){
System.out.print(arr[i]+" ");
}
System.out.println();
}
//计算当前队列中的有效个数
private int effectiveQuantity(){
return (rear + maxSize - front) % maxSize;
}
public void showFirst(){
if (isNull()){
System.out.println("队列空,无下一个取出元素~~");
}
System.out.println(arr[front]);
}
}