队列是先进先出的线性表;
队列由于是线性表,因此也有顺序存储和链式存储两种实现方式;
一、顺序存储实现
由于队列的特性是:从队尾添加,从对头删除,因此如果让数组的尾部用作队尾,数组的头部用作队头,则删除元素时,时间复杂度为O(n);
因此我们需要用循环数组实现,并且维护两个属性 front、rear,front用来记录队头的位置,rear记录队尾的下一个位置;比如:
这样能够充分利用数组的空间,但是预先规定了空间就不能再改变;
代码实现如下:
package org.xiazdong.list;
public class MyArrayQueue<T> {
private int front;
private int rear;
private int length;
private T[] t;
public MyArrayQueue(){
front = rear = length = 0;
t = (T[])new Object[20];
}
public void append(T e) throws Exception{
if(length==t.length){
throw new QueueOverFlowException();
}
length++;
t[rear] = e;
rear = (rear+1)%t.length;
}
public T remove() throws Exception{
if(length<=0){
throw new QueueOffFlowException();
}
T e = t[front];
length--;
front = (front + 1)%t.length;
return e;
}
public int getSize(){
return length;
}
}
class QueueOverFlowException extends Exception{
public QueueOverFlowException(){
super();
}
@Override
public String getMessage() {
return "队列溢出";
}
}
class QueueOffFlowException extends Exception{
public QueueOffFlowException(){
super();
}
@Override
public String getMessage() {
return "队列空";
}
}
二、链式存储实现
链式存储简单的说就是单链表+front、rear指针;
front指向头结点,rear指向最后一个节点;
回顾一下头结点的定义:不具有任何意义的节点,为了操作单链表方便而使用;
代码实现如下:
package org.xiazdong.list;
public class MyListQueue<T> {
private BeginNode front;
private Node rear;
public MyListQueue(){
front = new BeginNode(0,null);
rear = front;
}
public void append(T e){
Node n = new Node(e,null);
rear.next = n;
rear = n;
front.elem++;
}
public T remove() throws Exception{
if(front.elem<=0){
throw new Exception();
}
T e = front.next.elem;
front.next = front.next.next;
front.elem--;
if(front.elem==0){
rear = front;
}
return e;
}
class Node {
private T elem;
Node next;
public Node() {
elem = null;
next = null;
}
public Node(T elem, Node next) {
this.elem = elem;
this.next = next;
}
}
class BeginNode extends Node {
int elem;
public BeginNode(int elem, Node next) {
this.elem = elem;
this.next = next;
}
}
}