顺序循环队列

队列的基本概念

队列(简称队)是一种特殊的线性表,队列的数据元素以及数据元素间的逻辑关系和线性表完全相同,差别就是线性表允许在任意位置插入和删除,而队列只允许在一端进行插入操作而在另一端进行删除操作。

队列中允许进行插入操作的一端称为队尾,允许进行删除的一端称为队头。

faf7d1e6-07b1-44bb-9752-5fcc113a0648


操作集合

(1)入队列append(obj):把数据元素插入队尾;

(2)出队列delete():把队头数据元素删除并由元素返回;

(3)取队头数据元素getFront():取队头数据元素并由函数返回;

(4)判断队列是否为空isEmpty():为空返回true,不为空返回false。

顺序队列的“假溢出”问题


上图中,front指针指向队头元素,rear指针指向队尾元素的下一个位置。图(d)中b、c、d出队后,front指针指向元素e,rear指针在数组外面。假设这个队列的总个数不超过5个,但目前如果接着入队的话,因数组末尾元素已经被占用,再向后加就会产生数组越界的错误,可实际上队列在下标为0、1、2、3、4的地方还是空闲的,我们把这种现象叫做“假溢出”。
解决办法

一是将队列元素向前“平移”(占用0至rear-front-1);
二是将队列看成首尾相连,即循环队列(0..m-1)。
在循环队列下,仍定义front=rear时为队空,而判断队满则用两种办法,一是用“牺牲一个单元”,即rear+1=front(准确记是(rear+1)%m=front,m是队列容量)时为队满。
另一种解法是“设标记”方法,如设标记tag,tag等于0情况下,若删除时导致front=rear为队空;tag=1情况下,若因插入导致front=rear则为队满。

顺序循环队列

队列之顺序队列与循环队列

 循环队列的基本操作

     循环队列中进行出队、入队操作时,头尾指针仍要加1,朝前移动。只不过当头尾指针指向向量上界(QueueSize-1)时,其加1操作的结果是指向向量的下界0。这种循环意义下的加1操作可以描述为:
① 方法一:
    if(i+1==QueueSize) //i表示front或rear
        i=0;
    else
        i++;
② 方法二--利用"模运算"
    i=(i+1)%QueueSize;
循环队列边界条件处理
  循环队列中,由于入队时尾指针向前追赶头指针;出队时头指针向前追赶尾指针,造成队空和队满时头尾指针均相等。因此,无法通过条件front==rear来判别队列是"空"还是"满"。 
     解决这个问题的方法至少有三种:
  ① 另设一布尔变量以区别队列的空和满;
  ② 少用一个元素的空间。约定入队前,测试尾指针在循环意义下加1后是否等于头指针,若相等则认为队满(注意:rear所指的单元始终为空);
  ③使用一个计数器记录队列中元素的总数(即队列长度)。

源代码

队列接口Queue.java

package 队列;
public interface Queue {
//入队列
public void append(Object obj)throws Exception;

//出队列
public Object delete()throws Exception;

//取对头数据元素
public Object getFront()throws Exception;

//是否为空
public boolean isEmpty();
}

顺序循环队列类SeqQueue.java

package 队列;

public class SeqQueue implements Queue {
static final int defaultSize=10;
int front;//对头
int rear;//对尾
int count;//元素个数统计器
int maxSize;//最大数据元素个数
Object[]data;//保存队列元素的数组

public SeqQueue(){//无参数构建函数
initiate(defaultSize);
}
public SeqQueue(int sz){//带参构建函数
initiate(sz);
}
public void initiate(int sz){//初始化
maxSize=sz;
front=rear=0;
count=0;
data=new Object[sz];
}

@Override
public void append(Object obj) throws Exception {
// TODO 自动生成的方法存根
if(count>0&&front==rear){
throw new Exception("队列已满!");
}

data[rear]=obj;
rear=(rear+1)%maxSize;
count++;
}


@Override
public Object delete() throws Exception {
// TODO 自动生成的方法存根
if(count==0){
throw new Exception("队列已空!");
}
Object temp=data[front];
front=(front+1)%maxSize;
count--;
return temp;
}


@Override
public Object getFront() throws Exception {
// TODO 自动生成的方法存根
if(count==0){
throw new Exception("队列已空!");
}
return data[front];
}


@Override
public boolean isEmpty() {
// TODO 自动生成的方法存根
return count==0;
}

}

测试类 SeqQueueTest.java

package 队列;

public class SeqQueueTest {

public static void main(String[] args)throws Exception {
SeqQueue queue=new SeqQueue();
queue.append("a");
queue.append("b");
queue.append("c");
queue.append("d");
queue.append("e");

queue.delete();
queue.append("f");
queue.delete();

while(!queue.isEmpty()){
System.out.println(queue.delete());
}
}
}

参考来源:http://blog.sina.com.cn/s/blog_5b9734c501015wjp.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值