利用数组实现循环队列
- 循环队列为空的条件:font==rear
- 循环队列已满的条件:(rear+1)%length=font
- 循环队列实际元素个数的计算方式:(rear-font+length)%length
- 循环队列队头、队尾指针的后移规则:font=(font+1)%length rear=(rear+1)%length
package basicKnowledge.集合框架.queue;
/**
* @基本功能:利用数组实现一个循环队列
* @program:summary
* @author:peicc
* @create:2019-07-24 10:11:06
**/
public class MyArrayQueue<E> {
private int size;//队列元素个数
private int length;//数组实际长度
private int font;//指向队头
private int rear;//指向队尾
private Object[] element;//存储队列元素
private final int DEFAULT_SIZE=10;
//无参构造函数
MyArrayQueue(){
this.element=new Object[DEFAULT_SIZE];
this.font=0;
this.rear=0;
this.length=DEFAULT_SIZE;
}
//MyArrayQueue类型的构造函数,实现队列初始化
MyArrayQueue(MyArrayQueue<? extends E> c){
//自己去实现
}
//返回元素的个数
public int getSize(){
return (rear-font+length)%length;
}
//入队
public boolean enQueue(E e){
//首先判断队列是否已满
if((rear+1)%length==font){
return false;
}
element[rear]=e;//元素置于队尾
rear=(rear+1)%length;//rear后移一位,若到末尾则转移到数组头部
return true;
}
//出队,获取并移除队列头部元素
public E deQueue(){
//首先判断队列是否为空
if(font==rear){
return null;
}
E ele=(E)element[font];
font=(font+1)%length;//rear后移一位,若到末尾则转移到数组头部
return ele;
}
//获取队列头部元素,但不删除
public E getFirst(){
if(font==rear){
return null;
}
return (E)element[font];
}
//队列是否为空
public boolean isEmpty(){
return font==rear?true:false;
}
public static void main(String[] args) {
MyArrayQueue<Integer> myArrayQueue=new MyArrayQueue<Integer>();
for(int i=0;i<5;i++){
myArrayQueue.enQueue(i);
}
System.out.println();
System.out.println("********打印输出********");
while(!myArrayQueue.isEmpty()){
System.out.print(myArrayQueue.deQueue()+" ");
}
}
}
利用链表实现队列
package basicKnowledge.集合框架.queue;
/**
* @基本功能:利用链表实现队列
* @program:summary
* @author:peicc
* @create:2019-07-24 10:59:06
**/
public class MyListQueue<E> {
Node<E> font;//指向队头
Node<E> rear;//指向队尾
private static class Node<E>{
E item;
Node<E> next;//指向下一个节点
Node(E ele){
this.item=ele;
this.next=null;
}
}
//入队
public void enQueue(E e){
Node<E> newNode=new Node(e);
if(font==null){//如果链表为空
font=newNode;
rear=newNode;
}else{
rear.next=newNode;
rear=newNode;
}
}
//出队
public E deQueue(){
if(font==null){
return null;
}
Node<E> node=font;
font=font.next;
return node.item;
}
public static void main(String[] args) {
MyListQueue myListQueue=new MyListQueue();
for(int i=0;i<5;i++){
myListQueue.enQueue(i);
}
System.out.println("*********** 输出队列元素**********");
while(myListQueue.font!=null){
System.out.print(myListQueue.deQueue());
}
}
}
两种实现方式比较
- 时间上,两种方式的基本操作都是常数时间O(1)
- 空间上,循环队列有一个固定的长度,所以就有了存储元素个数和空间浪费的问题。而链队列需要一个指针域,会产生一些空间上的开销,但一颗接受,而且空间上更加灵活
- 在确定队列长度最大值的情况下,建议用循环队列。如果无法预估队列的长度,则使用链队列
参考文献
1.《大话数据结构》
2《数据结构与算法分析》