java先进先出 循环队列_队列的理解和实现(一) ----- 循环队列(java实现)

什么是队列

我们都知道栈是先进后出的一种线性表,与之相反的是,队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端进行删除。举个例子来说,在生活中我们买东西需要进行排队,最先排队的可以最早的离开队伍,而排在最后面的需要最后离开队伍。在队列当中,允许插入的一端称为队尾,而允许删除的一段称为队头。和栈与线性表类似,队列也分为顺序队列和链队列。

普通队列所存在的问题

在使用数组实现的队列中,入队的操作就是将尾指针rear右移一个单位(加一),然后将元素值赋值给rear单位。出队时,则是头指针front后移一个单位(加一)。当进行了一定数量的入队和出队操作后,可能会出现这样的情况:

尾指针rear已指到数组的最后有一个元素,即rear=maxSize-1,此时若再数组的前面部分可能还有很多闲置空间,即这种溢出并非是真的没有可用的存储空间,故称这种溢出现象为“假溢出”。显然,必须要解决这一块假溢出的问题,否则顺序队列就没有太多使用价值。

解决假溢出一般情况下有两个方式:

1.在普通队列中设置元素实际个数变量size,在每次入队或者出队时将size和maxSize进行比较,从而避免假溢出。使用这种方式未免有些繁琐。

2.使用循环队列,将队列掰弯,也就是将队列看成环状结构,即data[0]为紧接着data[MaxLen-1]的单元,为相邻的元素,首位成为一个环,如下所示:

e3ac6679092dc6bf0d7bb7e4d7a2d81a.png

理解循环队列

首先要确认的是,循环队列仍然是基于数组实现的,使用一组地址连续的存储单元依次存放从队头到队尾的元素,且仍然设置两个指针front,rear。注意的是,其实这两个指针是整数型的,起得是知识的作用便于理解,所以称之为指针。这两个指针,一个指着队头,一个指着队尾。

这两个指针可以看做动态的过程,即这两个指针其实是互相追赶的。在追赶中就是队列中元素添加和删除的过程。当rear追到front时就表示队列已经满了,当front追上rear时就表示队列已经空了。

循环队列的实现过程

一般情况下,会少用一个元素空间,即队列空间大小为m时,有m-1个元素就认为是队满。这样当头尾指针的值相同时,则认为对空;当尾指针在循环意义上加1后是等于头指针,则认为队满。

当添加一个元素时,(queue.rear + 1) % maxSize;

当删除一个元素时,(queue.front + 1) % maxSize;

队空的条件:queue.front == queue.rear    //当队列添加元素到rear的下一个元素是队头的时候,也就是转圈子要碰头了,我们就认为队列满了。

队满的条件:(queue.rear + 1) % maxSize == queue.front    //当队列删除元素到head=rear的时候,我们认为队列空了。

循环队列的代码实现

package 循环队列;

public class LoopQueue {

int front;

int rear;

int maxSize;

Object queueList[];

//初始化队列

public LoopQueue() {

maxSize = 1024;

queueList = new Object[maxSize];

rear = 0;

front = 0;

}

//初始化队列

public LoopQueue(int maxSize) {

this.maxSize = maxSize;

queueList = new Object[maxSize];

rear = 0;

front = 0;

}

//判断队列是否为空

public boolean isEmpty() {

return this.front == this.rear ? true : false;

}

//判断队列是否已满

public boolean isFull() {

return ((rear + 1) % this.maxSize) == this.front ? true : false;

}

//取循环队列的对头元素

public Object getFront() {

if(isEmpty() == false) return queueList[this.front];

else {

System.out.println("ERROR:Queue is Empty");

return "";

}

}

//入队

public void enQueue(Object e) {

if(isFull() == false) {

this.queueList[this.rear] = e;

this.rear = (this.rear + 1) % this.maxSize;

}

else System.out.println("ERROR::Queue is Full");

}

//出队

public void deQueue() {

if(isEmpty() == false) {

this.front = (this.front + 1) % this.maxSize;

}

else System.out.println("ERROR::Queue is empty");

}

//获取队列长度

public int QueueLength() {

return (this.rear - this.front + this.maxSize) % this.maxSize;

}

public static void main(String[] args) {

LoopQueue q = new LoopQueue();

System.out.println("队列是否为空:" + q.isEmpty());

System.out.println("队列是否为满:" + q.isFull());

System.out.println("队列长度:" + q.QueueLength());

q.enQueue(5);

q.enQueue(4);

q.enQueue(3);

q.enQueue(2);

q.enQueue(1);

System.out.println("队列长度:" + q.QueueLength());

q.deQueue();

System.out.println("队列是否为空:" + q.isEmpty());

System.out.println("对头元素:" + q.getFront());

System.out.println("队列长度:" + q.QueueLength());

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值