一、顺序存储,即数组存储
这部分跟上文提到的栈的顺序存储没什么不同,只不过多了一个队尾指针
/** * 队列的顺序存储(数组) * @param <E> */ public class Queue<E>{ private Object[] data; private int front; private int rear; private int maxSize; public Queue(){ this.maxSize = 10; data = new Object[this.maxSize]; } public Queue(int initialSize){ data = new Object[initialSize]; this.maxSize = initialSize; front = rear = 0; } /** * 判断是否为空 * @return */ public boolean empty(){ return rear==front? true: false; } /** * 入队列 * @param e */ public void add(E e){ if (rear == maxSize){ throw new RuntimeException("队列已满"); } data[rear] = e; rear ++; } /** * 出队列 * @return */ public E delete(){ if (empty()){ throw new RuntimeException("空队列异常"); } E e =(E) data[front]; data[front] = null; // 释放队列的元素 front ++; return e; } /** * 队列中元素个数 * @return */ public int length(){ return rear-front; } public static void main(String[] args){ Queue<Integer> q = new Queue<>(); q.add(5); q.add(4); q.add(3); q.add(2); q.add(1); while (!q.empty()){ System.out.println(q.delete()); } } }
二、 栈的循环存储
先简单说明一下,为什么需要使用循环?跟上面的顺序存储又有什么不同?栈为什么又没有循环存储?其实很简单,栈是半封闭性的,只有栈顶可以进行增加和删除操作,而队列是两头开。因此相对于栈,队列的长度也是不变的(使用数组存储时),但是可以移动指针,从而动态的提高内存利用率,因此 队列可以使用循环,而栈不可以(队列对栈说:小样,我有两个洞口,可以来回跑~)
/**
* 队列的循环存储
* @param <E>
*/
public class LoopQueue<E>{
public Object[] data;
private int maxSize; //队列容量
private int rear;
private int front;
private int size = 0;
public LoopQueue(){
this.maxSize = 10;
data = null;
}
public LoopQueue(int initalSize){
if (initalSize > 0){
data = new Object[initalSize];
this.maxSize = initalSize;
rear = front = 0;
}
}
/**
* 判断是否为空
* @return
*/
public boolean empty(){
return size==0? true : false;
}
/**
* 进队列
* @param e
*/
public void add(E e){
if (size == maxSize){
throw new RuntimeException("队列已满,无法插入新元素!");
}
data[rear] = e;
rear = (rear+1) % maxSize;
size ++;
}
/**
* 出队列
* @return
*/
public E pop(){
if (empty()){
throw new RuntimeException("空队列异常");
}
E e = (E) data[front];
data[front] = null;
front = (front+1) % maxSize;
size --;
return e;
}
public int queueLength(){
return size;
}
public static void main(String[] args){
LoopQueue<Integer> lq = new LoopQueue<>();
lq.add(5);
lq.add(4);
lq.add(3);
lq.add(2);
lq.add(1);
while (!lq.empty()){
System.out.println(lq.pop());
}
}
}
三、 队列的单链表存储
前面介绍了单链表,栈,队列的顺序存储,因此我觉得使用单链表存储队列应该会很容易, 依葫芦画瓢嘛,程序猿的基本修养。但是,失败往往发掘于细节和用心。失败部分用红色字体表示出来了,而出现错误的原因是:栈增加元素的时候是将新元素放在栈顶上,而队列增加新元素的时候是将元素放在队尾,其指向下一个元素是空指针,因此不能照搬。
/**
* 队列的链式存储
* @param <E>
*/
public class LinkQueue<E>{
class Node<E>{
E data;
Node<E> next;
public Node(E data, Node next){
this.data = data;
this.next = next;
}
}
Node<E> front;
Node<E> rear;
int size = 0;
public LinkQueue(){
front = rear = null;
}
/**
* 判断队列是否为空
* @return
*/
public boolean empty(){
return size==0? true: false;
}
/**
* 进队列
* @param e
*/
public void add(E e){
if (empty()){
front = new Node<>(e, null);
rear = front;
}else{
// rear = new Node<>(e, rear);
Node<E> newNode = new Node<>(e, null);
rear.next = newNode;
rear = newNode;
}
size ++;
}
/**
* 出队列
* @return
*/
public E pop(){
if (empty()){
throw new RuntimeException("空队列异常");
}
Node<E> value = front;
E e = value.data;
front = front.next;
value.next = null;
size --;
return e;
}
/**
* 队列的长度
* @return
*/
public int linkQueueLength(){
return size;
}
public static void main(String[] args){
LinkQueue<Integer> lq = new LinkQueue<>();
lq.add(5);
lq.add(4);
lq.add(3);
lq.add(2);
lq.add(1);
while (!lq.empty()){
System.out.println(lq.pop());
}
}
}