队列学习

来源:互联网 发布:网络主播可以做广告吗 编辑:程序博客网 时间:2024/06/05 03:57

队列也是一种线性表,具有两种数据存储结构,队列中只允许在队尾插入和在队头删除,是先进先出表。

和堆栈一样我们先定义队列中基本的功能并提供接口:

package StackAndQueue;/*** @author sun* 创建时间:2017年4月3日上午10:44:29*//* * 封装队列的常用操作,提供接口: * 入队列append(obj):把数据元素obj插入队尾 * 出队列delete():把队头数据元素删除并由函数返回 * 取队头数据元素getFront():取队头数据元素并由函数返回 * 非空否notEmpty():非空否,若非空返回true,否则返回false */public interface Queue {public void append(Object obj)throws Exception;public Object delete()throws Exception;public Object getFront()throws Exception;public boolean notEmpty();}

顺序队列:顺序存储结构的队列,有两个指针,队头front指向队列中排在第一位的元素,队尾rear指向队列中排在最后的元素的下一个位置,类似于顺序堆栈中的top。

假溢出问题:给定长度的数组来作为顺序队列的存储空间,有新元素加入rear就会向后移位,有元素删除front也会向后移位,当rear已经指向数组最后元素的后一位置,但数组并没有用掉所有空间,因为有部分出队列,这时再次添加元素就会发生溢出,即所谓的假溢出。

解决办法:采用顺序循环队列,rear指向数组最后一个位置时,再次添加就会自动到0。这样,我们下标的计算方法就不是简单加1,而是rear=(rear+1) % maxSize。

新的问题:解决了假溢出,但发现,当队列为空和队满时,都是rear==front,无法区分两种状态。

解决办法:(1)少用一个存储空间,判满:(rear+1) % maxSize == front;判空:rear == front。

    (2)设置一个标志位tag,入队tag=1,出队tag=0,判满:rear == front && tag==1;判空:rear == front && tag==0。

    (3)设置一个计数器count,入队加1,出队减1,判满:count>0 && rear == front;判空:count == 0;该法最好。

解决了问题,下面就是建立队列类:

定义顺序循环队列类:

package StackAndQueue;/*** @author sun* 创建时间:2017年4月3日上午11:02:55*//*建立顺序循环队列类实现接口 * 队头front指向第一个元素,队尾rear指向最后一个入队列元素的下一个位置。 * 循环队列的队满和队空,都有rear==front * 我们采用计数器来判断队满和队空 */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);}private void initiate(int sz){//初始化maxSize = sz;front = rear = 0;count = 0;data = new Object[sz];}public void append(Object obj)throws Exception{if(count>0 && rear==front){throw new Exception("队列已满!");}data[rear] = obj;rear = (rear+1) % maxSize;count++;}public Object delete()throws Exception{if(count==0){throw new Exception("队列已空!");}Object temp = data[front];front = (front+1) % maxSize;count--;return temp;}public Object getFront()throws Exception{if(count==0){throw new Exception("队列已空!");}return data[front];}public boolean notEmpty(){return count != 0;}}

定义链式队列类:(不再重复建立结点类)

package StackAndQueue;/*** @author sun* 创建时间:2017年4月3日下午7:57:18*//* * 建立链式队列类实现接口 * 链式队列和堆栈一样通常设计为不带头结点的结构; * 链式队列中front指向第一个元素,rear指向最后一个元素(注意:不是最后一个元素的下一个位置) * */public class LinQueue implements Queue {Node front;Node rear;int count;public LinQueue(){initiate();}private void initiate(){front = rear = null;//这里不能等于0,因为front和rear不代表下标,而是指针count = 0;}public void append(Object obj){//不用抛出异常,因为链式存储结构不会存在满的情况Node newNode = new Node(obj,null);if(rear!=null)rear.next = newNode;rear = newNode;if(front==null)front = newNode;//毕竟没有头结点,不能用front.next,会造成头结点count++;}public Object delete()throws Exception{if(count==0){throw new Exception("队列已空");}Node temp = front;front = front.next;count--;return temp.getElement();}public Object getFront()throws Exception{if(count==0){throw new Exception("队列已空");}return front.getElement();}public boolean notEmpty(){return count!=0;}}


0 0