三、隊列
1、概念
隊列是一種遵循 FIFO
(first-in-first-out)的集合數據結構,即最先放到隊列中的元素,也是最先被獲取到的
它底層可以用數組來實現,也可以用鏈表來實現。它有2個指針,分別指向頭節點和尾節點,添加元素時向後移動尾節點,移除元素時向後移動頭節點
2、常用方法
- put 添加元素到隊列中
- take 移出隊列的首個元素(向後移動頭節點)
- peek 取出隊列的首個元素(不移動頭節點)
3、示例
1)數組隊列
class ArrayQueue<T> {
private final int length;
private Object[] array;
private int head; // 指向本次要移出的元素的前一個位置
private int tail; // 指向本次要添加的元素的前一個位置
public ArrayQueue(int length) {
this.length = length;
this.array = new Object[this.length];
this.head = -1;
this.tail = -1;
}
public void put(T element) {
if (isFull()) {
return;
}
this.tail++;
array[tail] = element;
}
public T take() {
if (isEmpty()) {
return null;
}
this.head++;
@SuppressWarnings("unchecked")
T element = (T)array[head];
if (head == tail) {
head = -1;
tail = -1;
}
return element;
}
@SuppressWarnings("unchecked")
public T peek() {
if (isEmpty()) {
return null;
}
return (T)array[head + 1];
}
public int size() {
return tail - head;
}
@Override
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder sBuilder = new StringBuilder("[");
for (int i = head + 1, size = i + size(); i < size; i++) {
sBuilder.append(array[i]);
if (i != size - 1) {
sBuilder.append(", ");
} else {
sBuilder.append("]");
}
}
return sBuilder.toString();
}
public boolean isFull() {
return tail == length - 1;
}
public boolean isEmpty() {
return -1 == head && head == tail;
}
}
2)鏈表隊列
class LinkedQueue<T> {
private final int length;
private Node<T> head; // 頭節點指向本次可以取出的節點
private Node<T> tail; // 尾節點指向最後一個節點
private int size;
public LinkedQueue(int length) {
this.length = length;
this.head = null;
this.tail = null;
this.size = 0;
}
public void put(T element) {
if (isFull()) {
return;
}
Node<T> add = new Node<T>(element);
if (null == head) {
this.head = add;
}
if (null != tail) {
tail.next = add;
}
this.tail = add;
this.size++;
}
public T take() {
if (isEmpty()) {
return null;
}
T element = head.element;
if (head == tail) { // 最後一個元素,將尾節點也置爲空
this.tail = null;
}
this.head = head.next;
this.size--;
return element;
}
public T peek() {
if (isEmpty()) {
return null;
}
return head.element;
}
public int size() {
return size;
}
@Override
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder sBuilder = new StringBuilder("[");
Node<T> node = this.head;
while (true) {
sBuilder.append(node.element);
if (null == node.next) {
break;
}
sBuilder.append(", ");
node = node.next;
}
sBuilder.append("]");
return sBuilder.toString();
}
public boolean isFull() {
return size == length;
}
public boolean isEmpty() {
return 0 == size;
}
private static class Node<T> {
private final T element;
private Node<T> next;
private Node(T element) {
this.element = element;
}
@Override
public String toString() {
return (null != element) ? element.toString() : "null";
}
}
}
3)循環隊列
class CircleQueue<T> {
private final int length;
private Object[] array;
private int head; // 指向隊頭
private int tail; // 指向隊尾
public CircleQueue(int length) {
this.length = length + 1; // 多出一個位置,用於存放上一次取出的元素。更新指針時訪問不到它
this.array = new Object[this.length];
this.head = 0;
this.tail = 0;
}
public void put(T element) {
if (isFull()) {
return;
}
array[tail] = element;
tail = (tail + 1) % length;
}
public T take() {
if (isEmpty()) {
return null;
}
@SuppressWarnings("unchecked")
T element = (T)array[head];
head = (head + 1) % length;
return element;
}
@SuppressWarnings("unchecked")
public T peek() {
if (isEmpty()) {
return null;
}
return (T)array[head];
}
public int size() {
return (tail + length - head) % length;
}
public boolean isFull() {
return (tail + 1) % length == head;
}
public boolean isEmpty() {
return head == tail;
}
@Override
public String toString() {
if (isEmpty()) {
return "[]";
}
StringBuilder sBuilder = new StringBuilder("[");
for (int i = head, size = i + size(); i < size; i++) {
sBuilder.append(array[i % length]);
if (i != size - 1) {
sBuilder.append(',').append(' ');
}
}
sBuilder.append(']');
return sBuilder.toString();
}
}