【数据结构】队列
什么是队列?
队列是一种线性数据结构,要理解它,其实非常简单,举个例子。
假如高速公路上有一条隧道,所有通过隧道的车辆只允许从隧道的入口驶入,从隧道出口驶出,不允许逆行。因此,要想让车辆驶出隧道,只能按照车辆的驶入顺序,先驶入的车辆先驶出,后驶入的车辆后驶出,任何车辆都无法跳过它前面的车辆提前驶出。
队列是一种线性数据结构,它不同于栈,队列中的元素只能先进先出(First In First Out,简称FIFO),队列的出口端叫队首,队列的入口段叫队尾。
队列的实现
1、入队(enqueue)
入队就是把新的元素放入队列中,只允许从队尾放入元素,并且新元素将会成为下一个新的队尾。
2、出队(dequeue)
出队就是把队首元素移除队列,出队元素的后一个元素成为新队首。
整体代码如下:
/** * 描述:队列所需的方法。 * * Create By ZhangBiao * 2020/5/10 */ public interface Queue<E> { /** * 入队操作 * * @param e */ void enqueue(E e); /** * 出队操作 * * @return */ E dequeue(); /** * 获取队首 * * @return */ E getFront(); /** * 获取队列元素个数 * * @return */ int getSize(); /** * 判断队列是否为空 * * @return */ boolean isEmpty(); }
/** * 描述:基于动态数组实现队列。 * <p> * Create By ZhangBiao * 2020/5/10 */ public class ArrayQueue<E> implements Queue<E> { private Array<E> array; public ArrayQueue() { array = new Array<>(); } public ArrayQueue(int capacity) { array = new Array<>(capacity); } @Override public void enqueue(E e) { this.array.addLast(e); } @Override public E dequeue() { return this.array.removeFirst(); } @Override public E getFront() { return this.array.getFirst(); } @Override public int getSize() { return this.array.getSize(); } @Override public boolean isEmpty() { return this.array.isEmpty(); } /** * 获取队列容量大小。 * * @return */ public int getCapacity() { return this.array.getCapacity(); } @Override public String toString() { StringBuilder result = new StringBuilder(); result.append("Queue: "); result.append("front ["); for (int i = 0; i < array.getSize(); i++) { result.append(array.get(i)); if (i != array.getSize() - 1) { result.append(", "); } } result.append("] tail"); return result.toString(); } }
循环队列的实现
注意:如果队列不断的出队,那么左边的内存空间就会浪费,这时就可以使用循环队列来维持队列容量。
循环队列是什么呢?
假设我们有一个这样的队列。如下:
这时执行一个入队操作,在数组不扩容的前提下,如何让新元素入队并确定新的队尾位置呢?可以利用已出队元素留下的空间,让队尾指针重新指向数组的首位。
这样一来,整个队列的元素就循环起来了。在物理存储上,队尾的位置可以在队首之前,当再有元素入队时,将其放入数组的首位,队尾指针后移即可。
一直到(tail + 1)% 数组长度 == front 时,代表队列已满。注意:队尾指针指向的位置永远空出一位,所以在循环队列中会浪费一个空间。
这就是所谓的循环队列。
整体代码如下:
/** * 描述:循环队列。 * <p> * Create By ZhangBiao * 2020/5/10 */ public class LoopQueue<E> implements Queue<E> { private E[] data; private int front; private int tail; private int size; public LoopQueue() { this(10); } public LoopQueue(int capacity) { data = (E[]) new Object[capacity + 1]; front = 0; tail = 0; size = 0; } @Override public void enqueue(E e) { if ((tail + 1) % data.length == front) { resize(getCapacity() * 2); } data[tail] = e; tail = (tail + 1) % data.length; size++; } /** * 扩容 * * @param newCapactiy */ private void resize(int newCapactiy) { E[] newData = (E[]) new Object[newCapactiy + 1]; for (int i = 0; i < size; i++) { newData[i] = data[(front + i) % data.length]; } data = newData; front = 0; tail = size; } @Override public E dequeue() { if (isEmpty()) { throw new IllegalArgumentException("Cannot dequeue from an empty queue."); } E ret = data[front]; data[front] = null; front = (front + 1) % data.length; size--; if (size == getCapacity() / 4 && getCapacity() / 2 != 0) { resize(getCapacity() / 2); } return ret; } @Override public E getFront() { if (isEmpty()) { throw new IllegalArgumentException("Queue is empty."); } return data[front]; } @Override public int getSize() { return size; } @Override public boolean isEmpty() { return front == tail; } public int getCapacity() { return data.length - 1; } @Override public String toString() { StringBuilder result = new StringBuilder(); result.append(String.format("Queue: size = %d , capacity = %d\n", size, getCapacity())); result.append("front ["); for (int i = front; i != tail; i = (i + 1) % data.length) { result.append(data[i]); if ((i + 1) % data.length != tail) { result.append(", "); } } result.append("] tail"); return result.toString(); } public static void main(String[] args) { LoopQueue<Integer> queue = new LoopQueue<>(); for (int i = 0; i < 10; i++) { queue.enqueue(i); System.out.println(queue); if (i % 3 == 2) { queue.dequeue(); System.out.println(queue); } } } }
相关推荐
koushr 2020-11-12
zhangxiafll 2020-11-13
kikaylee 2020-10-31
范范 2020-10-28
MILemon 2020-10-22
hugebawu 2020-10-12
LauraRan 2020-09-28
shenwenjie 2020-09-24
omyrobin 2020-09-23
guangcheng 2020-09-22
qiangde 2020-09-13
hanyujianke 2020-08-18
晨曦之星 2020-08-14
xiesheng 2020-08-06
KAIrving 2020-08-02
xiesheng 2020-08-02
范范 2020-07-30
chenfei0 2020-07-30