队列
1.数组模拟一次性队列
代码实现
package 队列;
/*
* 数组模拟一次性队列
*
* 这里在使用数组实现该队列时思维比较简单,但也同样使得该队列有些相当于 “一次性队列” ,即如果用很多次的话,可能就因为rear移动到
* 尾部,导致不能使用了;
*
* 这里使用双指针思想来使用数组实现队列,这样的好处是实现起来简单,但是队列内存不能复用,因为原先队列内元素占据的内存直接随着指针
* 的移动所舍弃了,即在删除元素时没有真正的删除;
* */
public class ArrayQueue {
private int[] res;
private int maxSize; //队列的最大总使用容量
private int rear; //指向队列尾部的元素的下标,尾指针
private int front; //指向队列头部的元素的前一个下标 ,前指针
public ArrayQueue(int maxSize){
this.maxSize = maxSize;
res = new int[maxSize];
rear = -1;
front = -1;
}
public boolean isFull(){
return rear == maxSize - 1;
}
public boolean isEmpty(){
return rear == front;
}
//从尾部加元素
public void addQueue(int num){
if(isFull()){
System.out.println("当前队列已经满了~~~~~");
return;
}
rear++; //尾指针移动
res[rear] = num;
}
//从头部拿出元素
public int getQueue(){
if(isEmpty()){
throw new RuntimeException("当前队列为空!");
}
front++; //头指针移动
return res[front];
}
//打印队列内的所有元素
public void showQueue(){
if(isEmpty()){
System.out.println("当前队列为空!");
return;
}
for(int i=front+1 ; i <= rear; i++){
System.out.println(res[i]+" ");
}
}
//查看头部元素
public int headQueue(){
if(isEmpty()){
throw new RuntimeException("当前队列为空!");
}
return res[front+1];
}
}
2.数组模拟环形队列
代码实现
package 队列;
/*
* 数组模拟环形队列
* 就是因为一次性队列浪费了太多空间,不能起到空间复用!
* 要想起到空间复用,就需要在头尾指针移动到maxSize时返回数组头部,即起到一种环形的思想!
* 而要实现这种环形思想,就需要使用 % 运算符来实现,即一旦头尾指针超过maxSize,便使其对maxSize取余数,
* 这样我们发现刚好可以使其返回头部!!!
* */
public class CircleQueue {
private int[] res;
private int maxSize; //队列的最大总使用容量,但是要注意的是由于我们最后一位空出来了,所以真正队列大小为maxSize-1
//如果不空出一位的话,isFull方法会错误的!
private int rear;
// rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定,尾指针
private int front;
// front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素,头指针
//需要注意的是front和rear都是以下标的形式!!!!所以是不能等于maxSize的
public CircleQueue(int maxSize){
this.maxSize = maxSize;
res = new int[maxSize];
rear = 0;
front = 0;
}
//当没满时,我们发现取余相当于没作用,所以二者必定不可能相等,因此此时二者没任何关系!
//当满了后,我们发现,此时头尾直接存在关系,即尾部+1刚好是头部的maxSize倍!!!
// 比如maxSize为10,那么此时头部为0,尾部为9,所以(9+1) % 10 == 0 ,移动一格后,为头 1 尾 0 ,所以 (0+1)% 10 == 1
public boolean isFull(){
return (rear+1) % maxSize == front;
}
//空时还是头尾相等,因为front是指向队列的第一个元素,rear是指向队列的最后一个的后一个,
// 你可能会想为什么不是rear == front-1 ,是因为如果只是第一个元素等下标等于最后一个元素下标只是能说明此时只有一个元素
//所以为空则代表,此时的头部和尾部的下一个在同一位置
public boolean isEmpty(){
return rear == front;
}
//从尾部加元素
public void addQueue(int num){
if(isFull()){
System.out.println("当前队列已经满了~~~~~");
return;
}
res[rear] = num;
rear = (rear+1) % maxSize; //防止越界,一旦越界便根据环形返回头部
}
//从头部拿出元素
public int getQueue(){
if(isEmpty()){
throw new RuntimeException("当前队列为空!");
}
int temp = res[front];
front = (front+1) % maxSize; //防止越界,一旦越界便根据环形返回头部
return temp;
}
//打印队列内的所有元素
public void showQueue(){
if(isEmpty()){
System.out.println("当前队列为空!");
return;
}
for(int i=front ; i < front+size(); i++){ // 从头指针开始,按个数枚举
System.out.printf("res[%d] = %d" ,i % maxSize,res[i%maxSize] ); //防止越界,一旦越界便根据环形返回头部
}
}
//查看队列的真正长度
public int size(){
return (rear+maxSize-front) % maxSize; //理解为 rear在前,front在后时的情况
}
//查看头部元素
public int headQueue(){
if(isEmpty()){
throw new RuntimeException("当前队列为空!");
}
//头部直接对准
return res[front];
}
}
class Test{
public static void main(String[] args) {
CircleQueue circleQueue = new CircleQueue(4);
//队列的最大总使用容量,但是要注意的是由于我们最后一位空出来了,所以真正队列大小为3
//所以此时创建的是一个最大长度为3的队列
circleQueue.addQueue(1);
circleQueue.addQueue(2);
System.out.println(circleQueue.isFull());
}
}