接口:
package fwb.queue;
/**
* @program: stack
* @description: 队列
* @author: fwb
* @create: 2019-05-27 19:24
**/
public interface Queue<E> {
/**
* @Description: 入队,在队尾插入
* @Param: [e]
* @return: void
*/
void enQueue(E e);
/**
* @Description: 出队,队首元素
* @Param: [e]
* @return: E
*/
E deQueue();
/**
* @Description: 返回队首元素但是不出队
* @Param: []
* @return: E
*/
E peek();
int getSize();
boolean isEmpty();
}
链表实现队列(推荐)
头插法:入队O(1),出队:O(n);
尾插法:入队O(n),出队:O(1);
优化:定义两个节点来存储队列的头和尾(可以类比于双向链表去理解)
package fwb.queue.Impl;
import fwb.queue.Queue;
/**
* @program: stack
* @description: 链表实现队列
* @author: fwb
* @create: 2019-05-27 20:06
**/
public class LinkedQueue<E> implements Queue<E> {
//当前队列的头结点
private Node head;
//当前队列的尾节点,用于元素的入队
private Node tail;
//当前队列的元素个数
private int size;
private class Node{
private E data;
private Node next;
public Node(E data,Node next){
this.data = data;
this.next = next;
}
}
@Override
public void enQueue(E e) {
Node newNode = new Node(e,null);
//当前队列为空
if(head == null){
head = tail = newNode;
}else{
tail.next = newNode;
tail = tail.next;
}
size++;
}
@Override
public E deQueue() {
if (isEmpty()){
System.err.println("队列为空");
return null;
}
E result = head.data;
head.data =null;
head = head.next;
size--;
return result;
}
@Override
public E peek() {
if (isEmpty()){
System.err.println("队列为空");
return null;
}
return head.data;
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
}
顺序表实现队列
package fwb.queue.Impl;
import fwb.queue.Queue;
/**
* @program: stack
* @description: 数组实现队列
* @author: fwb
* @create: 2019-05-27 20:40
**/
public class ArrayQueue<E> implements Queue<E> {
private Object[] elementData;//泛型不能直接new数组
private int head;
private int tail;
public ArrayQueue(int maxSize) {
elementData = new Object[maxSize];
}
@Override
public void enQueue(E e) {
//队列长度指的时当前数组有多少元素
if (tail == elementData.length){
if (head == 0){
System.err.println("当前队列已经满了");
return;
}else{
//如果前面有没有利用到的数组空间,数组迁移,将前面空间填满,但是如果队列元素过多,这种方法会很慢
//所以需要环形队列。
for (int i = head;i < tail;i++){
elementData[i - head] = elementData[i];
}
//重新赋值头尾节点指针
tail = tail - head;
head = 0;
}
}
//tail从1开始,指向数组中队列最后一个元素的下一位
elementData[tail++] = e;
}
@Override
public E deQueue() {
if (isEmpty()){
System.err.println("当前队列为空");
return null;
}else{
return (E)elementData[head++];
}
}
@Override
public E peek() {
if (isEmpty()){
System.err.println("当前队列为空");
return null;
}
return (E)elementData[head];
}
@Override
public int getSize() {
return tail - head;
}
@Override
public boolean isEmpty() {
return head == tail;
}
}
循环队列:
package fwb.queue.Impl;
import fwb.queue.Queue;
/**
* @program: stack
* @description: 循环队列
* @author: fwb
* @create: 2019-05-27 21:33
**/
public class ArrayLoopQueue<E> implements Queue<E> {
private Object[] elementData;
private int head;
private int tail;
private int size;
public ArrayLoopQueue(int maxSize) {
//多开辟一块空间用来区分环形队列到底是空还是满
elementData = new Object[maxSize + 1];
}
@Override
public void enQueue(E e) {
if ((tail + 1)%elementData.length == head){
System.err.println("队列已经满了");
return;
}
elementData[tail] = e;
// 不能直接tail++,需要按取模的方式得到他的下一位
tail = (tail + 1) % elementData.length;
size++;
}
@Override
public E deQueue() {
if (isEmpty()){
System.err.println("队列为空");
return null;
}
E result = (E) elementData[head];
head = (head + 1) % elementData.length;
size--;
return result;
}
@Override
public E peek() {
if (isEmpty()){
System.err.println("队列为空");
return null;
}
return (E) elementData[head];
}
@Override
public int getSize() {
//head = 4,tail = 1,size = (4 + 1) % 8 = 5
//head = 4,tail = 5,size = (4 + 5) % 8 = 1
//不嗯能直接用tail - head
return size;
}
@Override
public boolean isEmpty() {
return head == tail;
}
}