先进先出队列(简称队列)是一种基于先进先出(FIFO)策略的集合类型。可以使用数组和链表实现。
API
成员函数(Item 是泛型变量) | 功能 |
---|---|
Queue() | 创建空队列 |
void enqueue() | 添加一个元素 |
Item dequeue() | 删除最早添加的元素 |
boolean isEmpty() | 队列是否为空 |
int size() | 队列中的元素数量 |
实现
两种实现都支持 forEach 迭代。
数组实现
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
public class ResizingArrayQueue<Item> implements Iterable<Item> {
// 初始化队列数组大小
private static final int INIT_CAPACITY = 8;
// 队列元素数组
private Item[] q;
// 当前队列的元素数量
private int n;
// 队列头部元素
private int first;
// 队列尾部元素
private int last;
/**
* 初始化空队列
*/
public ResizingArrayQueue() {
q = (Item[]) new Object[INIT_CAPACITY];
n = 0;
first = 0;
last = 0;
}
/**
* 当前队列是否为空
*
* @return 为空返回 true,否则放回 false
*/
public boolean isEmpty() {
return n == 0;
}
/**
* 当前队列的元素数量
*
* @return 元素数量
*/
public int size() {
return n;
}
/**
* 动态调整队列数组大小
*
* @param capacity
*/
private void resize(int capacity) {
assert capacity >= n;
Item[] copy = (Item[]) new Object[capacity];
for (int i = 0; i < n; i++) {
copy[i] = q[(first + i) % q.length];
}
q = copy;
first = 0;
last = n;
}
/**
* 添加一个元素
*
* @param item
*/
public void enqueue(Item item) {
if (n == q.length) resize(2 * q.length);
q[last++] = item;
if (last == q.length) last = 0;
n++;
}
/**
* 删除队列最早添加的元素
*
* @return 队列最早添加的元素
*/
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
Item item = q[first];
q[first] = null;
n--;
first++;
if (first == q.length) first = 0;
if (n > 0 && n == q.length / 4) resize(q.length / 2);
return item;
}
/**
* 查看队列最早添加元素(不删除)
*
* @return 队列最早添加的元素
*/
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
return q[first];
}
/**
* forEach 迭代
*
* @return
*/
public Iterator<Item> iterator() {
return new ArrayIterator();
}
private class ArrayIterator implements Iterator<Item> {
private int i = 0;
public boolean hasNext() {
return i < n;
}
public void remove() {
throw new UnsupportedOperationException();
}
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = q[(i + first) % q.length];
i++;
return item;
}
}
public static void main(String[] args) {
ResizingArrayQueue<String> queue = new ResizingArrayQueue<>();
for (int i = 0; i < 8; i++) {
// generator random string
int leftLimit = 97; // letter 'a'
int rightLimit = 122; // letter 'z'
int targetStringLength = 3;
Random random = new Random();
String generatedString = random.ints(leftLimit, rightLimit + 1)
.limit(targetStringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
queue.enqueue(generatedString);
}
System.out.println("isEmpty: " + queue.isEmpty());
System.out.println("size: " + queue.size());
System.out.println("peek: " + queue.peek());
System.out.println();
for (String s : queue) {
System.out.println("str: " + s);
}
}
}
其中在 resize() 和 next() 方法中有这么一句代码:
Item item = q[(i + first) % q.length];
还有 enqueue() 和 dequeue() 中的代码:
if (last == q.length) last = 0; // enqueue()
if (first == q.length) first = 0; // dequeue()
对应的是这种情况:
链表实现
package chapter1.c1_3;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Random;
public class LinkedQueue<Item> implements Iterable<Item> {
private int n;
private Node first;
private Node last;
/**
* 内部结点类
*/
private class Node {
private Item item;
private Node next;
}
/**
* 初始化空栈
*/
private LinkedQueue() {
first = null;
last = null;
n = 0;
assert check();
}
/**
* 是否为空栈
*
* @return 为空返回 true,否则返回 false
*/
public boolean isEmpty() {
return first == null;
}
public int size() {
return n;
}
/**
* 查看最早添加的元素(不删除)
*
* @return 最早添加的元素
*/
public Item peek() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
return first.item;
}
/**
* 添加一个元素
*
* @param item
*/
public void enqueue(Item item) {
Node oldLast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldLast.next = last;
n++;
assert check();
}
/**
* 删除最早添加的元素
*
* @return 最早添加的元素
*/
public Item dequeue() {
if (isEmpty()) throw new NoSuchElementException("Queue underflow");
Item item = first.item;
first = first.next;
n--;
if (isEmpty()) last = null;
assert check();
return item;
}
/**
* 元素转化为字符串
*
* @return 字符串
*/
public String toString() {
StringBuilder s = new StringBuilder();
for (Item item : this) {
s.append(item).append(" ");
}
return s.toString();
}
/**
* 检测内部变量
*
* @return 全部通过返回 true,否则返回 false
*/
public boolean check() {
if (n < 0) {
return false;
} else if (n == 0) {
if (first != null) return false;
return last == null;
} else if (n == 1) {
if (first == null || last == null) return false;
if (first != last) return false;
return first.next == null;
} else {
if (first == null || last == null) return false;
if (first == last) return false;
if (first.next == null) return false;
if (last.next != null) return false;
int numberOfNodes = 0;
for (Node x = first; x != null && numberOfNodes <= n; x = x.next) {
numberOfNodes++;
}
if (numberOfNodes != n) return false;
Node lastNode = first;
while (lastNode.next != null) {
lastNode = lastNode.next;
}
return last == lastNode;
}
}
/**
* 支持 forEach 迭代
*
* @return
*/
@Override
public Iterator<Item> iterator() {
return new LinkedIterator();
}
private class LinkedIterator implements Iterator<Item> {
private Node current = first;
@Override
public boolean hasNext() {
return current != null;
}
@Override
public Item next() {
if (!hasNext()) throw new NoSuchElementException();
Item item = current.item;
current = current.next;
return item;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
public static void main(String[] args) {
ResizingArrayQueue<String> queue = new ResizingArrayQueue<>();
for (int i = 0; i < 8; i++) {
// generator random string
int leftLimit = 97; // letter 'a'
int rightLimit = 122; // letter 'z'
int targetStringLength = 3;
Random random = new Random();
String generatedString = random.ints(leftLimit, rightLimit + 1)
.limit(targetStringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
queue.enqueue(generatedString);
}
System.out.println("isEmpty: " + queue.isEmpty());
System.out.println("size: " + queue.size());
System.out.println("peek: " + queue.peek());
System.out.println();
for (String s : queue) {
System.out.println("str: " + s);
}
}
}
对应的图:
附件:
LinkedQueue.drawioResizingArrayStack.drawio
参考: