目录
一、引言
二、队列的抽象数据类型描述
三、顺序队列及其基本操作的实现
1.顺序队列的存储结构
2.循环顺序队列类的描述
一、引言
队列是另一种特殊的线性表,它的特殊性体现在队列只允许在表尾插入数据元素,在表头删除数据元素,所以队列也是一种操作受限的特殊的线性表,它具有先进先出或后进后出的特性。
二、队列的抽象数据类型描述
队列也是由n(n>=0)个具有相同类型的数据元素所构成的有限序列。队列的基本操作与栈类似,有以下6种:
(1)清空队列操作clear():将一个已经存在的队列置成空列队。
(2)判空操作isEmpty():判断一个队列是否为空,若为空,则返回true;否则,返回false。
(3)求队列长度操作length():返回队列中元素的个数。
(4)取队首元素操作peek():读取队首元素并返回其值。
(5)入队操作offer(x):将数据元素x插入到队列中使其成为新的队尾元素 。
(6)出队操作poll():删除队首元素并返回其值,若队列为空,则返回null。队列的抽象数据类型
用Java接口描述如下:
public interface IQueue {
public void clear();
public boolean isEmpty();
public int length();
public Object peek();
public void offer(Object x)throws Exception;
public Object poll();
}
三、顺序队列及其基本操作的实现
1.顺序队列的存储结构
与顺序栈类似,在顺序队列的存储结构中,需要分配块地址连续的存储区域来依次存放队列中从队首到队尾的所有元素。这样也可以使用一维数组来表示,假设数组名为queueElem,数组的最大容量为maxSize,由于队列的人队操作只能在当前队列的队尾进行,所以需加上变量front和rear来分别指示队首和队尾元素在数组中的位置,其初始值都为0。在非空栈中,front指向队首元素,rear指向队尾元素的下一个存储位置。
初始化队列时,令front=rear=0;入队时,直接将新的数据元素存入rear所指的在单元中,然后将rear值加1;出队时,直接取出front所指的存储单元中数据元素的值然后将front值加1。
因顺序队列的多次入队和出队操作后出现有存储空间,但不能进行人队操作的溢出现象称为“假溢出”。要解决“假溢出”问题,最好的办法就是把顺序队列所使用的存储空间看成是一个逻辑上首尾相连的循环队列。当rear或front到达maxSize-1 后,再加1就自动到0。这种转换可利用Java语言中对整型数据求模(或取余)运算来实现,即令rear= (rear+ 1)%maxSize。显然,当rear= maxSize-1时,rear加1后,rear的值就为0。这样,就不会出现顺序队列数组的头部有空的存储空间,而队尾却因数组下标越界而引起的假溢出现象。
2.循环顺序队列类的描述
解决循环顺序队列的队空和队满的判断问题通常可采用下面3种方法:
1)少用一个存储单元
当顺序存储空间的容量为maxSize时,只允许最多存放maxSize-1个数据元素.当队空队满时,队空的判断条件为: front== reart ),而队满的判断条件为: front== (reart +1)%maxSize。
2)设置一个标志变量
程序设计过程中引进个标志变量flag,其初始值置为0,每当人队操作成功后就置flag=1;每当出队操作成功后就置flag=0,则此时队空的判断条件为: front == rear && flag == 0,而队满的判断条件为: front==rear && flag==1。
3)设置一个计数器
在程序设计过程中引进个计数变 量num,其初始值置为 0,每当入队操作成功后就将计数变量num的值加1;每当出队操作成功后就将计数变量num的值减1,则此时队空的判断条件为: num == 0,而队满的判断条件为: num>0&&front == rear。
本文采用第一种方法来判断队空和队满的状态,下面是实现接口IQueue 的循环顺序队列类的Java语言的描述。
package Queue;
public class CircleSqQueue implements IQueue {
public Object[] queueElem;//队列储存空间
private int front;//队首的引用,若队列不空,指向队首元素
private int rear;//队尾的引用,若队列不为空,指向队尾元素的下一个储存位置
//循环队列类的构造函数
public CircleSqQueue(int maxSize){
front=rear=0;
queueElem=new Object[maxSize];
}
public void clear() {//队列置空
front=rear=0;
}
public boolean isEmpty() {//队列判空
return front==rear;
}
@Override
public int length() {//求队列的长度
return (rear-front+queueElem.length)%queueElem.length;
}
@Override
public Object peek() {//读取队首元素
if(front==rear){//队列为空
return null;}
else{
return queueElem[front];//返回队首元素
}
}
//入队
@Override
public void offer(Object x) throws Exception {
if((rear+1)%queueElem.length==front){//队列满
throw new Exception("队列已满");//抛出异常
}else{
queueElem[rear]=x;//x存入rear所指向的数组储存位置中,使其成为新的队尾元素
rear=(rear+1)%queueElem.length;//修改队尾指针
}
}
//出队
@Override
public Object poll() {
if(front==rear){//队列为空
return null;}
else{
Object t=queueElem[front];//取出队首元素
front=(front+1)%queueElem.length;//front值循环加1
return t;//返回队列的队首元素
}
}
}