1.基于数组的实现
队列的基本概念就是先进先出,但是如果采用数组来实现就会出现每次执行一次dequeue会把数组里面的每个元素都会移动一次,移动n次的时间复杂度就是O(n^2),我们想要优化它的dequeue操作,可以定义两个变量来记录它的栈顶和栈尾来进行入队和出队操作
/**
* Created by upupgogogo on 2018/4/26.下午6:02
*/
public class LoopQueue<E> implements Queue<E> {
private E[] data; //容器
private int size; //队列长度
private int front; //栈顶位置
private int tail; //栈尾位置
public LoopQueue(int capacity){
data = (E[]) new Object[capacity];
size = 0;
front = 0;
tail = 0;
}
public LoopQueue(){
this(10);
}
@Override
public int getSize(){
return this.size;
}
@Override
public boolean isEmpty(){
return size == 0;
}
@Override
public void enqueue(E e){
if (size == getCapacity() ){
resize(getCapacity() * 2); // 扩容
}
data[tail] = e;
tail = (tail + 1) % data.length; //这个是一个循坏的队列
size++;
}
@Override
public E dequeue(){
if(isEmpty())
throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size --;
if(size == getCapacity() / 4 && getCapacity() / 2 != 0)
resize(getCapacity() / 2);
return ret;
}
@Override
public E getFront(){
if(isEmpty())
throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
E ret = data[front];
return ret;
}
public int getCapacity(){
return data.length ;
}
private void resize(int capacity) {
E[] newData = (E[]) new Object[capacity];
for (int i = 0; i < size; i++)
newData[i] = data[(i+front) % data.length];
data = newData;
front = 0;
tail = size;
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append(String.format("Queue: size = %d , capacity = %d\n", size, getCapacity()));
res.append("front [");
for (int i = 0; i < size; i++){
res.append(data[(i+front) % data.length]);
if (i != size - 1)
res.append(", ");
}
res.append("] tail");
return res.toString();
}
2.基于链表的实现
链表本身会有一个头指针,它进行dequeue时时间复杂度是O(1),但是进行enqueue的操作却是O(n)级别的,我们可以设置一个tail变量来记录尾结点,这样enqueue操作也是O(1)级别的
/**
* Created by upupgogogo on 2018/5/9.下午7:43
*/
public class LinkedListQueue<E> {
private class Node{
public E e;
public Node next;
public Node(E e, Node next){
this.e = e;
this.next = next;
}
public Node(E e){
this(e, null);
}
public Node(){
this(null, null);
}
@Override
public String toString(){
return e.toString();
}
}
private Node head,tail;
private int size;
public LinkedListQueue() {
this.head = null;
this.size = 0;
this.tail = null;
}
public int getSize(){
return this.size;
}
boolean isEmpty(){
return size == 0;
}
public void enqueue(E e){
if (isEmpty()){ //如果队列是空的,那么设置tail和head都指向new Node(e)
tail = new Node(e);
head = tail;
}
else {
tail.next = new Node(e);
tail = tail.next;
}
size ++;
}
public E dequeue(){
if (isEmpty()){
throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
}
Node resNode = head;
head = head.next;
resNode.next = null;
size --;
return resNode.e;
}
public E getFront(){
if (isEmpty()){
throw new IllegalArgumentException("Cannot getFront from an empty queue.");
}
return head.e;
}
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Queue: front ");
Node cur = head;
while(cur != null) {
res.append(cur + "->");
cur = cur.next;
}
res.append("NULL tail");
return res.toString();
}
}