队列: 只允许在一端进行插入操作(队尾),在另一端进行删除操作(队头)。 队列的特征就是:先进先出。
队列的思想及实现也同样非常简单。在生活中的各种常常都需要排队进行,键盘中缓存区、操作系统中的作业调度等都有用到队列先进先出的思想。在这里同样用一个示意图展示队列的基本思想。
下面笔者才用数组存储元素,实现了一个循环队列。
队列中最重要的一个方法就是队列是否满的判断,
判断队列是否为满。队满: rear + 2 = front 或 front + maxSize -2 = rear
判断队列是否为空。队空: rear + 1 = front 或 front + maxSize -1 = rear
/** 判断队列是否为空。队空: rear + 1 = front 或 front + maxSize -1 = rear
* 通过数组容量比队列数据项的最大值大一,来区分对空和对满。
*/public booleanisEmpty(){return(rear+1== front|| front+ maxSize-1== rear);}/**判断队列是否为满。 队满: rear + 2 = front 或 front + maxSize -2 = rear
* 通过数组容量比队列数据项的最大值大一,来区分对空和对满。
*/public booleanisFull(){return(rear+2== front|| front+ maxSize-2== rear);}
**获取队列大小(元素个数):**可以通过队头队尾计算出队列的大小,也可以通过一个计数器,当入队是加1,出队是减1.
/** 获取队列的大小
*/public intqueueSize(){if(rear>= front){return rear- front+1;}else{return maxSize- front+(rear+1);}}
出队入队查看队头元素:
入队:
出队:
全部代码及测试:
package org.TT.Queue;/**
* 循环队列: 先进先出
* 队列同样是个概念上的辅助工具。这里采用数组完成队列的操作,仍然采用泛型
* 队列的数据项的入队、出队时间复杂度为常数 O(1)。
* 通过队头队尾指针的移动保存所有数据位置不动,而不是移动数据项。
* 在这里,数组的大小比队列存放数据元素大1,主要是为了方便队满的判断。
*/publicclassQueue<T>{private int maxSize;// 队列最多容纳数量private Object[] queueArray;private int front;// 队头private int rear;// 队尾private int size;publicQueue(int length){
maxSize= length;
queueArray=newObject[maxSize];
front=0;
rear=-1;
size=0;}/** 入队: 先将rear(队为指针) 加1, 后将数据项存入rear的位置。
* 当rear 指向maxSize -1 的位置时,将rear 设置为-1(循环队列),加1 后存入数据项。
*/publicvoidenQueue(T str){if(isFull()){// 入队之前先检查队列是否已满,已满则抛出异常。thrownewRuntimeException("队列已满,"+ str+" 不能入队!");}if(rear== maxSize-1){
rear=-1;}
queueArray[++rear]= str;// 先将 rear 加1,后取值
size++;}/**出队: 先取出front 的值,然后将front 减1
* 如果 front 超过了数组的顶端,将 front 设置为 0(循环队列)
*/
@SuppressWarnings("unchecked")publicTdeQueue(){if(isEmpty()){// 出队之前先检查队列是否为空, 为空则抛出异常。thrownewRuntimeException("队列为空,不能出队!");}T str=(T) queueArray[front++];// 先去 queueArray[front] 的值,后将front 加1if(front== maxSize){
front=0;}
size--;return str;}/**查看对头数据项
*/
@SuppressWarnings("unchecked")publicTpeek(){if(isEmpty()){// 查看队头时,判断是否为空, 为空则抛出异常。thrownewRuntimeException("队列为空!");}return(T) queueArray[front];}/** 判断队列是否为空。队空: rear + 1 = front 或 front + maxSize -1 = rear
* 通过数组容量比队列数据项的最大值大一,来区分对空和对满。
*/public booleanisEmpty(){return(rear+1== front|| front+ maxSize-1== rear);}/**判断队列是否为满。 队满: rear + 2 = front 或 front + maxSize -2 = rear
* 通过数组容量比队列数据项的最大值大一,来区分对空和对满。
*/public booleanisFull(){return(rear+2== front|| front+ maxSize-2== rear);}/** 获取队列的大小
*/public intqueueSize(){/* 可以通过队头队尾计算出队列的大小,也可以通过一个计数器,当入队是加1,出队是减1.
if(rear >= front){
return rear - front +1;
}else {
return maxSize - front + (rear + 1);
}
*/return size;}publicstaticvoidmain(String[] args){
Queue<String> queue=newQueue<>(5);
queue.enQueue("a");
queue.enQueue("b");
queue.enQueue("c");
queue.enQueue("d");
queue.deQueue();
queue.deQueue();
System.out.println("队列是否为空: "+ queue.isEmpty()+" 队列是否满: "+ queue.isFull());
System.out.println("队列大小:"+ queue.queueSize());
int size= queue.queueSize();for(int i=0; i< size; i++){
String str= queue.deQueue();
System.out.print(str+" ");}}}
结果:
关于链队列只是在单链表的基础上多了简单的修改,在单链表中添加一个尾指针即可,每次入队、出队只分别对单链表的队尾和队首进行插入和删除在操作,由于链队没有队满的限制,所以相对于非常简单,而判空操作只需判断 front == rear 是否成立。 在这里笔者就不列出链队列。在java库中也有队列相关的接口及实现并且还有双端队列、优先队列等类。
转载:https://blog.csdn.net/tanjiquan/article/details/50677141