线性数据结构(三) 栈
Stack 是一种后进先出的数据结构(FILO), 基本的操作有 push(), pop(), peek(), size() 和 isEmpty().
因为它只能从一边进出, 所以是倒序的操作.所以可能想到的应用场景应该是各种对于顺序的操作. 以及相邻两个元素进行对比. 虽然它的操作很简单, 但是根据进栈和出栈的顺序不同, 可以得出不同的结果.
1 | 栈内元素: 1, 2, 3 |
A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class.
For example:
Deque
Java 中 stack 的实现通常会使用 Deque 这个 interface, 而不再使用 Stack 这个类了. 具体原因:
- 对于最新的 Java framework 来说, Stack 的线程安全显得太冗余.
- 通过 LinkedList 和 ArrayList 实现的 Deque 可以实现 Deque 和 Stack 的各种增删改查功能. 这样使得数据结构的整合更加统一, 使用 generic 类型来创建对象也更符合 Java OOP 的设计理念.
- 最后 LinkedList 和 ArrayList 都不是 Synchronized, 所以开销更小.
使用 Deque 接口:
operation | FistElement | Last Element | ||
---|---|---|---|---|
return type | exception | null | Exception | null |
insert | addFirst | offerFirst | addLast | offerLast |
remove | removeFirst | pollFirst | removeLast | removeFirst |
examine | getFirst | peekFirst | getLast | peekLast |
代码实现:
使用 LinkedList
1 | public class MyStackLL<E> { |
使用 Array
1 | public class MyStackAL<E> { |
所有操作的时间复杂度均为 O(1), 使用 array 的扩容方法 amortize 的时间复杂度依然是 O(1).
because the initial capacity is n. At the time we need to extend the capacity of the stack, it takes O(n) to copy the elements, and push operation will take O(1) for the upcoming n elements. When we add up the time of copy and adding, the average time complexity for each of upcoming elements will be O(n) + O(n) / n = O(2). Thus the amortized time complexity is O(1).