java 队列的使用_java 队列基础操作

http://www.cnblogs.com/fuck1/p/5996116.html

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

队列中允许进行插入操作的一端称为队尾,允许进行删除操作的一端称为队头。队列的插入操作通常称作入队列,队列的删除操作通常称作出队列。最简单的例子就是我们平时的排队,先进先出。

顺序队列的存储结构

下图是一个有6个存储空间的顺序队列的动态示意图,图中front指示队头,rear指示队尾。

4ecb7a9632e2b9ef549666fa5c25cb05.png

~顺序队列的假溢出现象

假溢出是由于队尾rear的值和队头front的值不能由所定义数组下界值自动转为数组上界值而产生的。因此,解决的方法是把顺序队列所使用的存储空间构造成一个逻辑上首尾相连的循环队列( Circular Queue)。

~解决方法

当rear和front达到maxSize-1后,再加1就自动到0。这样,就不会出现顺序队列数组的头部已空出许多存储空间,但队尾却因数组下标越界而引起溢出的假溢出问题。这里在代码里面会详细解释~

66c10424d1d64531bd3e4efee5826921.png

在操作完成后,该队列中会有两个空格没有数据元素保存,造成资源浪费,这就是假溢出现象。

//==========================

//使用自定义的queue接口

//队列接口

Queue interface

//队列接口

public interfaceQueue {//入队

public void append(Object obj) throwsException;//出队

public Object delete() throwsException;//获得对头元素

public Object getFront() throwsException;//判断是否为空

public booleanisEmpty();

}

//循环链表的具体实现

/*

* 循环顺序队列

*/

public class CircleSequenceQueue implements Queue {

static final int defaultsize = 10;// 默认队列的长度

int front; // 对头

int rear; // 队尾

int count;// 统计元素个数的计数器

int maxSize; // 队的最大长度

Object[] queue; // 队列,使用数组实现

// 默认构造

public CircleSequenceQueue() {

init(defaultsize);

}

public CircleSequenceQueue(int size) {

// 通过给定长度进行构造

init(size);

}

public void init(int size) {

maxSize = size;

front = rear = 0;

count = 0;

queue = new Object[size];

}

@Override

public void append(Object obj) throws Exception {

// TODO Auto-generated method stub

if (count > 0 && front == rear) {

throw new Exception("队列已满");

}

// 队尾插入数据

queue[rear] = obj;

// 通过这种方法让对标索引值不停的重复!!!

rear = (rear + 1) % maxSize;

count++;

}

@Override

public Object delete() throws Exception {

// TODO Auto-generated method stub

if (isEmpty()) {

throw new Exception("队列为空");

}

// 去除对头的元素,同时修改对头的索引值

Object obj = queue[front];

// 对头索引值,一样通过+1驱魔运算来实现循环索引效果

front = (front + 1) % maxSize;

count--;

return obj;

}

@Override

public Object getFront() throws Exception {

// TODO Auto-generated method stub

if (!isEmpty()) {

return queue[front];

} else {

// 对为空返回null

return null;

}

}

@Override

public boolean isEmpty() {

// TODO Auto-generated method stub

return count == 0;

}

}

//得到循环链表后,对其进行应用,之类主要是模拟卖票窗口

·  实例:使用顺序循环队列和多线程实现一个排队买票的例子。

·  生产者(等候买票)

·  消费者 (买票离开)

//代码的分割线,使用生产者消费者模式进行设计,主要是使用同步机制

//卖票窗口

public classWindowQueue {//卖票的队列默认长度10

int maxSize = 10;

CircleSequenceQueue queue= newCircleSequenceQueue(maxSize);//用来统计卖票的数量,一天最多卖100张票?

int num = 0;boolean isAlive = true; //判断是否继续卖票//排队买票,使用同步机制

public synchronized void producer() throwsException {//count队列中的元素个数,如果该值小于maxSize则可以买票

if (queue.count

queue.append(num++); //等待买票的数量+1

System.out.println("第" + num + "个客户排队等待买票");this.notifyAll(); //通知卖票线程可以卖票了

}//如果满了

else{try{

System.out.println("队列已满...请等待");this.wait(); //队列满时,排队买票线程等待,其实等待卖票队伍里面离开一个人后来唤醒自己

}catch(Exception e) {

e.printStackTrace();

}

}

}//排队卖票,使用同步机制

public synchronized void consumer() throwsException {//count队列中的元素个数,如果该值大于0,则说明有票可以继续卖票

if (queue.count > 0) {

Object obj=queue.delete();//第几个人买到票了

int temp =Integer.parseInt(obj.toString());

System.out.println("第" + (temp + 1) + "个客户排队买到票离开队列");//如果当前队列为空,并且卖出票的数量的大于等于100说明卖票要结束

if (queue.isEmpty() && this.num >= 100) {this.isAlive = false;

}//排队队伍离开一个人,可以进来一个人进行买票了。

this.notifyAll(); //通知买票线程可以买了,唤醒买票线程

}//如果满了

else{try{

System.out.println("队列已空...请进入队伍准备买票");this.wait();//队列空时,排队卖票线程等待,其实等待买票队伍里面进来一个人后买票来唤醒自己

}catch(Exception e) {

e.printStackTrace();

}

}

}

}

//下面的两个类是生产者与消费者的具体实现,实现runnable接口

//买票者

public class Producer implementsRunnable {//买票窗口

WindowQueue queue;//保证和消费者使用同一个对象

publicProducer(WindowQueue queue) {this.queue =queue;

}

@Overridepublic voidrun() {//TODO Auto-generated method stub// while (queue.num < 100) {try{//执行买票,消费者

queue.producer();

}catch(Exception e) {

e.printStackTrace();

}

}

}

}

//卖票者

public class Consumer implementsRunnable {

WindowQueue queue;//保证卖票与买票同步

publicConsumer(WindowQueue queue) {this.queue =queue;

}

@Overridepublic voidrun() {//判断是否可以继续卖票

while(queue.isAlive) {try{//卖票

queue.consumer();

}catch(Exception e) {

e.printStackTrace();

}

}

}

}

Testcode

public classTest {public static void main(String[] args) throwsException {/** CircleSequenceQueue queue = new CircleSequenceQueue();

* queue.append("a"); queue.append("b"); queue.append("c");

* queue.append("d"); queue.append("e");

*

* while (!queue.isEmpty()) { System.out.print(queue.delete() + " "); }*/

//卖票与买票模拟,使用同一个窗口对象

WindowQueue queue = newWindowQueue();//生产者

Producer P = newProducer(queue);//消费者

Consumer c = newConsumer(queue);//排队买票线程

Thread pThread = newThread(P);//买票线程

Thread cThread = newThread(c);

pThread.start();//开始排队买票

cThread.start(); //卖票

}

}

Test Code

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值