用队列实现栈
使用队列实现栈的下列操作:
- push(x) - 元素x入栈
- pop() - 移除栈顶元素
- top() - 获取栈顶元素
- empty() - 返回栈是否为空
注意:
- 你只能使用队列的基本操作-也就是
push to back
,peek/pop from front
,size
,状语从句:is empty
这些操作的英文合法的。 - 你所使用的语言也许不支持队列。你可以使用list或者deque(双端队列)来模拟一个队列,只要是标准的队列操作即可。
- 你可以假设所有操作都是有效的(例如,对一个空的栈不会调用pop或者顶操作)。
知识点
Stack
继承Vector类,后进先出的值的排列,Stack类是同步的,效率不高。官方一般建议使用ArrayDeque代替Stack
常用方法:
- empty:判断stack是否为空
- peek:返回栈顶端的元素
- pop:弹出栈顶的元素,出栈操作只是删除栈顶元素,并不返回该元素,内部执行了peek()方法
- push:将元素压入栈
- size:返回栈中的元素个数
- search:返回最靠近顶端的目标元素到顶端的距离
Queue
java.util.Queue接口,用以支持队列的常见操作,该接口扩展了java.util.Collection接口。public interface Queue extends Collection { }
除了基本的 Collection 操作外,队列还提供其他的插入、提取和检查操作。每个方法都存在两种形式:
- 抛出异常(操作失败时)类型: 一般为Collection方法 :
- add(e):插入,将指定的元素插入队列,成功返回true,如果当前无可用空间,则抛出IllegalStateException
- remove():移出,获取并移除队列的头
- element():检查,获取但不移除队列的头
- 返回特殊值(null 或 false,取决于操作)类型:
- offer(e):插入,将指定的元素插入此队列,如果当前无可用空间,则返回 null
- poll():移出,获取并移除队列的头,如果此队列为空,则返回null
- peek():检查,获取但不移除队列的头,如果此队列为空,则返回null
注意:Queue尽量避免使用抛出异常的add()、remove()、element()方法,而是要使用返回特殊值的offer()、poll()、peek()方法,
它们的优点是通过返回值可以判断成功与否
Queue 实现通常不允许插入 null 元素,尽管某些实现(如 LinkedList)并不禁止插入null。
即使在允许null的实现中,也不应该将null插入到Queue中,因为null也用作poll方法的一个特殊返回值,表明队列不包含元素。
Deque
public interface Deque extends Queue { ... }
一个线性 collection,支持在两端插入和移除元素。
Deque(double ended queue —双端队列),通常读为“deck”。
Deque既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。
Deque是Queue的子接口。
Deque有两个比较重要的类:ArrayDeque
和LinkedList
使用栈时: 用ArrayDeque的push和pop方法;
使用队列时: 使用ArrayDeque的add和remove方法。
接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。因为此接口继承了队列接口Queue,
所以其每种方法也存在两种形式:
一种形式在操作失败时抛出异常,
对头:
插入:addFirst(e)
移出:removeFirst()
检查:getFrist()
队尾:
插入:addLast(e)
移出:removeLast()
检查:getLast()
另一种形式返回一个特殊值(null 或 false,具体取决于操作)。
对头:
插入:offerFirst(e)
移出:pollFirst()
检查:peekFrist()
队尾:
插入:offerLast(e)
移出:pollLast()
检查:peekLast()
删除指定元素:boolean removeFirstOccurrence(e);
删除队列中第一个出现的boolean removeLastOccurrence(e);
删除队列中最后一个出现的e, 如果不存在或者空或其它返回false,成功删除(即改变了队列)则返回true
Deque迭代器:
正向迭代器: dq.iterator
反向迭代器:Iterator descendingIterator(); // 得到Iterator类型的反向迭代器
在将双端队列用作队列时,将得到 FIFO(先进先出)行为。
将元素添加到双端队列的末尾,从双端队列的开头移除元素。从Queue接口继承的方法完全等效于Deque方法:
Queue方法 / Dequeue方法
插入:
add(e) / addLast(e) – 插入元素,抛异常
offer(e) / offerLast(e) – 插入元素,如果当前无可用空间,返回null
移出:
remove() / removeFirst() – 获取并移除队列头
poll() / pollFirst() – 获取并移除队列头,如果此队列为空,则返回null
检查:
element() / getFirst() – 获取但不移除队列头
peek() / peekFirst() – 获取但不移除队列头,如果此队列为空,则返回null用作 LIFO(后进先出)堆栈。应优先使用此接口而不是Stack类。
在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出。堆栈方法完全等效于Deque方法:
堆栈方法 / Dequeue方法
push(e) / addFirst(e) — 插入元素
pop() / removeFirst() — 获取并移除队列头
peek() / peekFirst() — 获取但不移除队列头
ArrayDeque
数组实现的Deque,可以指定其capacity,但不过由于双端队列本身数据结构的限制,要求只能在初始化的时候指定capacity,没有像ArrayList那样随时都可以调整的ensureCapacity方法,
构造器中指定其初始的capacity:ArrayDeque(int numElements); // 初始元素个数,默认长度是16
ArrayDeque的使用方法就是上面的Deque的使用方法,基本没有对Deque拓展什么方法;
ArrayDeque是Deque 接口的一种具体实现,是依赖于可变数组来实现的。ArrayDeque 没有容量限制,可根据需求自动进行扩容。ArrayDeque 可以作为栈来使用,效率要高于Stack;ArrayDeque 也可以作为队列来使用,效率相较于基于双向链表的LinkedList也要更好一些
代码
使用ArrayDeque实现
1 | class MyStack { |