队列
1.队列是一个有序列表,可以用数组或者链表来实现
2.遵循先入先出的原则
一.数组模拟队列
数组模拟队列的思路
1.队列数组的声明如图,其中的maxSize是该队列的最大容量
2.队列的输出和输入分别从前后端来处理,需要两个索引front和rear分别记录前端和后端,增加数组rear会进行改变,取出数组front会进行改变
数组模拟队列的实现方法
判断队列是否为空(isEmpty)
1.当rear==front时说明队列为空
判断队列是否已满(isFull)
1.当rear==maxSize-1时说明队列存满
数组队列存入数组(addQueue)
1.先判断数组是否已满(已满返回false表示数据加入失败)
2…尾指针往后移(rear+1),再加入数据(返回true表示数据加入成功)
取出队列中的数据(getQueue)
1.首先需要判断队列是否为空
2.为空抛出异常
3.不为空front后移,取出数据并返回
展示数据
1.首先判断队列是否为空(为空抛出异常)
2.循环展示数组中的数据
查看队列头的数据
1.首先判断队列是否为空(为空抛出异常)
2.返回队列头的数据但是front索引不往后移
代码实现
//数组模拟队列
public class arrayQueue {
private int maxSize;//表示数组的最大容量
private int front;//头部索引
private int rear;//尾部索引
private int[]arr;
//创建队列的构造器
public arrayQueue(int maxSize)
{
this.maxSize=maxSize;//得到队列的大小
arr=new int[maxSize];//构造出数组
front=-1;
rear=-1;//front指向队列头的前一个位置,rear指向队列尾
}
//判断队列是否为空
public boolean isEmpty()
{
return rear==front;
}
//判断队列是否满
public boolean isFull()
{
return rear==maxSize-1;
}
public boolean addQueue(int number)
{
//首先判断队列是否已经满了
if(isFull())
return false;//队列满了,数添加失败,返回false
rear++;//尾索引后移
arr[rear]=number;
return true;//数据添加成功返回true
}
//获取队列的数据,出队列
public int getQueue()
{
//首先判断队列是否为空
if(isEmpty())
{
//队列为空,抛出异常
throw new RuntimeException("队列为空");//异常本身会导致程序的结束,不需要return
}
front++;//头指针后移
return arr[front];//返回得到的值
}
//显示队列所有的数据
public void show()
{
//首先还是需要判断队列是否为空
if(isEmpty())
{
throw new RuntimeException("队列为空");
}
for(int temp:arr)
{
System.out.print(temp+" ");
}
}
//查看队列头
public int peek()
{
//首先判断队列是否为空
if(isEmpty())
{
throw new RuntimeException("队列为空");
}
return arr[front+1];
}
}
代码分析
一.注意事项:
1.在展示数组,取出数组或者加入数据时需要注意首先判断该数组是否有数据或者数组为空,所以在判断后我们可以根据需求抛出异常,代码中的异常抛出后程序回自动停止运行,所以并不需要特设返回值。
2.注意索引的位置:front索引在第一个元素的前一位,rear索引在队尾元素
二.代码缺点:
在代码中我们可以看出队列中的元素被释放后得到的空间就不可以再次重复利用,所以我们在此代码的基础上进行改进,使其能够重复利用被释放掉的空间
三.改进方案
将此数组修改为一个循环数组,使其空间可以得到重复利用,下面的具体的修改过程
数组模拟循环队列
思路
1.首先需要对front索引进行调整:front指向的不再是第一个元素的前一个位置,而是就指向第一个元素的所在位置,初始值为0
2.对rear指针进行调整:rear指向最后一个元素的后一个位置,而不是最后一个元素的所在位置,初始值为0
3.当队列满时的判断条件:(rear+1)%maxSize=front
4.当队列为空的条件:rear=front
(调整rear和front的索引含义的目的就在于3和4条件的判断)
5.队列中有效的数据的个数:(rear+maxSize-front)%maxSize
代码实现
public class circleArrayQueue {
private int maxSize;//表示数组的最大容量
private int front;//头部索引
private int rear;//尾部索引
private int[]arr;
//创建队列的构造器
public circleArrayQueue(int maxSize)
{
this.maxSize=maxSize;//得到队列的大小
arr=new int[maxSize];//构造出数组
front=0;
rear=0;//front指向队列头的前一个位置,rear指向队列尾(指针的初始位置进行改变)
}
//判断队列是否为空
public boolean isEmpty()
{
return rear==front;//由于rear进行了改变,其表示队尾数据的下一个数据,所以只有当队列为空的时候rear才会等于front
}
//判断队列是否满
public boolean isFull()
{
return (rear+1)%maxSize==front;//若队列满那么说明rear的下一个位置就是front
}
public boolean addQueue(int number)
{
//首先判断队列是否已经满了
if(isFull())
return false;//队列满了,数添加失败,返回false
arr[rear]=number;
rear=(rear+1)%maxSize;
return true;//数据添加成功返回true
}
//获取队列的数据,出队列
public int getQueue()
{
//首先判断队列是否为空
if(isEmpty())
{
//队列为空,抛出异常
throw new RuntimeException("队列为空");//异常本身会导致程序的结束,不需要return
}
int answer=arr[front];
front=(front+1)%maxSize;//取出数据,调整指针的顺序改变(指针也可能回回到数组头部),还额外需要一个临时变量
return answer;//返回得到的值
}
//显示队列所有的数据
public void show()
{
//首先还是需要判断队列是否为空
if(isEmpty())
{
throw new RuntimeException("队列为空");
}
for(int i=front;i<front+size();i++)
{
System.out.println(arr[i%maxSize]);
}
}
//查看队列头
public int peek()
{
//首先判断队列是否为空
if(isEmpty())
{
throw new RuntimeException("队列为空");
}
return arr[front];
}
public int size()
{
return (rear+maxSize-front)%maxSize;
}
}
代码分析
在此优化中,灵活的使用了取余操作,使得队列的满,空,大小判断等得到了更好的实现