4、循环队列
1、循环队列
上次基于动态数组实现的队列,出队是 O(n) 级别的,性能不高,这里用另外一种思路来实现队列
使用两个变量 front 和 tail,分别代表数组第一个元素的索引和最后一个元素的后一个索引
使用 data[front] 出队,data[tail] 入队
队列为空:size == 0
队列为满:size == length
/**
* 循环队列
* 使用 size, 不浪费空间
* 队列为空: size == 0
* 队列为满: size == length
*/
public class LoopQueue<E> implements Queue<E> {
private E[] data;
private int front;
private int tail;
private int size;
public LoopQueue(int capacity) {
data = (E[]) new Object[capacity];
front = tail = size = 0;
}
public LoopQueue() {
this(10);
}
@Override
public void enqueue(E e) {
if (size == data.length) resize(data.length * 2);
data[tail] = e;
tail = (tail + 1) % data.length;
size++;
}
@Override
public E dequeue() {
if (isEmpty()) throw new RuntimeException("队列为空");
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size--;
if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
return ret;
}
@Override
public E getFront() {
if (isEmpty()) throw new RuntimeException("队列为空");
return data[front];
}
@Override
public int getSize() {
return size;
}
@Override
public boolean isEmpty() {
return size == 0;
}
public int getCapacity() {
return data.length;
}
/**
* 动态数组
*/
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity];
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 sb = new StringBuilder();
sb.append(String.format("LoopQueue2: size = %d, capacity = %d\n", size, getCapacity()));
sb.append("Front [");
for (int i = 0; i < size; i++) {
sb.append(data[(i + front) % data.length]);
if (i != size - 1) sb.append(", ");
}
sb.append("] Tail");
return sb.toString();
}
}
2、双端队列
/**
* 双端队列
* 使用 size, 不浪费空间
* 队列为空: size == 0
* 队列为满: size == length
*/
public class Deque<E> {
private E[] data;
private int front;
private int tail;
private int size;
public Deque(int capacity) {
data = (E[]) new Object[capacity];
front = tail = size = 0;
}
public Deque() {
this(10);
}
public void addFront(E e) {
if (size == data.length) resize(data.length * 2);
front = (front != 0) ? (front - 1) : (data.length - 1);
data[front] = e;
size++;
}
public void addLast(E e) {
if (size == data.length) resize(data.length * 2);
data[tail] = e;
tail = (tail + 1) % data.length;
size++;
}
public E removeFront() {
if (isEmpty()) throw new RuntimeException("队列为空");
E ret = data[front];
data[front] = null;
front = (front + 1) % data.length;
size--;
if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
return ret;
}
public E removeLast() {
if (isEmpty()) throw new RuntimeException("队列为空");
tail = (tail != 0) ? (tail - 1) : (data.length - 1);
E ret = data[tail];
data[tail] = null;
size--;
if (size == data.length / 4 && data.length / 2 != 0) resize(data.length / 2);
return ret;
}
public E getFront() {
if (isEmpty()) throw new RuntimeException("队列为空");
return data[front];
}
public E getLast() {
if (isEmpty()) throw new RuntimeException("队列为空");
return (tail != 0) ? data[tail - 1] : data[data.length - 1];
}
public boolean isEmpty() {
return size == 0;
}
public int getSize() {
return size;
}
public int getCapacity() {
return data.length;
}
private void resize(int newCapacity) {
E[] newData = (E[]) new Object[newCapacity];
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 sb = new StringBuilder();
sb.append(String.format("Deque: size = %d, capacity = %d\n", getSize(), getCapacity()));
sb.append('[');
for (int i = 0; i < getSize(); i++) {
sb.append(data[(i + front) % data.length]);
if (i != getSize() - 1) sb.append(", ");
}
sb.append(']');
return sb.toString();
}
}
本文来自博客园,作者:lidongdongdong~,转载请注明原文链接:https://www.cnblogs.com/lidong422339/p/17302826.html