#栈 Stack
- 栈也是一种线性结构
- 相比数组,栈对应的操作是数组的子集
- 只能从一端添加元素,也只能从一端取出元素,这一端称为栈顶
- 栈是一种后进先出的数据结构(Last In First Out – LIFO)
- 在计算机的世界里,栈拥有着不可思议的作用

其实⾮常好理解,我们将栈可以看成⼀个箱⼦:
- 往箱⼦⾥⾯放东⻄叫做⼊栈
- 往箱⼦⾥⾯取东⻄叫做出栈
- 箱⼦的底部叫做栈底
- 箱⼦的顶部叫做栈顶
说到栈的特性,肯定会有⼀句经典的⾔语来概括: 先进后出(LIFO, Last In First Out)
- 往箱⼦⾥边放苹果,箱⼦底部的苹果想要拿出来,得先把箱⼦顶部的苹果取⾛才⾏
栈的应用
栈的基本实现
- Interface Stack
- void push(E)
- E pop()
- E peek()
- int getSize()
- boolean isEmpty
- 从用户角度看,支持这些操作就好
- 具体底层实现,用户不关心
- 实际底层有多种实现方式
定义栈的基本实现的接口,可以不同底层实现方式实现定义栈的接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package demo.structure.stack;
public interface Stack<E> {
int getSize();
boolean isEmpty();
void push(E e);
E pop();
E peek(); }
|
数组(Array)实现栈
以数组为底层实现方式(依赖上面的数组实现)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| package demo.structure.stack;
import demo.structure.array.Array;
public class ArrayStack<E> implements Stack<E> {
Array<E> array;
public ArrayStack(int capacity) { array = new Array<>(capacity); }
public ArrayStack() { array = new Array<>(); }
@Override public int getSize() { return array.getSize(); }
@Override public boolean isEmpty() { return array.isEmpty(); }
@Override public void push(E e) { array.addLast(e); }
@Override public E pop() { return array.removeLast(); }
@Override public E peek() { return array.getLast(); }
public int getCapacity() { return array.getCapacity(); }
@Override public String toString() { StringBuilder result = new StringBuilder(); result.append("Stack:"); result.append('['); for (int i = 0; i < array.getSize(); i++) { result.append(array.get(i)); if (i != array.getSize() - 1) { result.append(","); } } result.append("] top"); return result.toString(); } }
|
测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package demo.structure.stack;
import java.util.Random;
public class ArrayStackMain { public static void main(String[] args) { ArrayStack<Integer> stack = new ArrayStack<>(); for (int i = 0; i < 5; i++) { stack.push(i); System.out.println(stack); } stack.pop(); System.out.println(stack); } }
|
执行结果:

栈的应用实现
括号匹配
- 有效的括号(leetcode 20题)
- 栈顶元素反应了在嵌套的层次关系中,最近的需要匹配的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package demo.structure.stack;
import java.util.Stack;
public class ValidParentheses {
public boolean isValid(String s) { Stack<Character> stack = new Stack<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(' || c == '[' || c == '{') { stack.push(c); } else { if (stack.isEmpty()) { return false; } char topChar = stack.pop(); if (c == ')' && topChar != '(') { return false; } if (c == ']' && topChar != '[') { return false; } if (c == '}' && topChar != '{') { return false; } } } return stack.isEmpty(); }
public static void main(String[] args) { System.out.println("[{()}],是否匹配?" + new ValidParentheses().isValid("[{()}]")); System.out.println("[]{}(),是否匹配?" + new ValidParentheses().isValid("[]{}()")); System.out.println("[({)}],是否匹配?" + new ValidParentheses().isValid("[({)}]")); } }
|
执行结果:

栈的复杂度分析
ArrayStack<E>
void push(E) O(1)均摊
E pop() O(1)均摊
E peek() O(1)
int getSize() O(1)
boolean isEmpty O(1)