刷力扣239的时候,发现使用一个数据结构Deque会让实现很简单。于是看源码学习一下。Deque继承Queue,但是包含更多方法。
Deque
Deque就是doulbe end queue,就是两端都可以操作的队列。
public interface Deque<E> extends Queue<E> {
void addFirst(E e);
void addLast(E e);
boolean offerFirst(E e);
......
}
ArrayDeque
让我们来看一下具体实现类ArrayDeque,可以看到,底层是用一个数组elements来实现的。先看几个Queue经典操作。
public class ArrayDeque<E> extends AbstractCollection<E>
implements Deque<E>, Cloneable, Serializable
{
transient Object[] elements;
public void addFirst(E e) {
if (e == null)
throw new NullPointerException();
elements[head = (head - 1) & (elements.length - 1)] = e;
if (head == tail)
doubleCapacity();
}
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
Queue
public boolean offer(E e) {
return offerLast(e);
}
public E poll() {
return pollFirst();
}
public E peek() {
return peekFirst();
}
///Stack
public void push(E e) {
addFirst(e);
}
public E pop() {
return removeFirst();
}
addFirst()
我们可以从这个方法得知这个数组是怎么储存数据的。
elements[head = (head - 1) & (elements.length - 1)] = e;长度只能是2的指数倍,所以elements.length - 1,就是低位都是1,比如长度为16,那么为01111(就相当于取模操作,主要为了解决负数-1). head刚进来初始化为0,0-1=-1,二进制为11111,&操作后为01111=15,所以第一个数被存在下标为15的地方也就是数组的尾巴,下一个add的数将会被存在(15-1)&(01111)=14,所以是倒着存的。以此类推。
这相当于是一个循环数组
addLast()
同理现在再看addLast()就很简单了,tail = (tail + 1) & (elements.length - 1),从前往后加对象。
相当于队列的操作
- poll() 可以看到调用了pollFirst(),顾名思义,就是把queue中第一个元素给poll了,那么肯定有pollLast(),poll掉最后一个元素。first是数组下标为0,last是数组下标为size的。
- peek()调用了peekFirst(),同理还可以使用peekLast()
- offer()调用了offerLast(),就是往数组尾巴上加入元素。
相当于stack的操作
- push()
- peek()
- pop()