介绍 栈对应的操作是数组的子集。
对于栈的理解,其实它就是一个数组,只不过只能从一端添加元素,也只能从这一端删除元素。
栈是一种后进先出的数据结构(LIFO)。
栈的应用
编辑器中的 Undo 操作,通常就是使用一个栈来维护的。
程序调用的系统栈。比如我们执行 A 函数,执行到第 2 行后其调用了 B 函数,那么 A 函数执行就暂停,开始调用 B 函数,此时就有一个栈来维护这个调用过程,类似 A2 就被 push 到栈里,记录 A 函数当前执行到第 2 行。类似的 B3 也可能被 push 到栈中去执行 C 函数,C 函数执行完了继续执行 B,那么栈就会执行一个 pop 操作。通过栈顶的记录,计算机就找到了继续执行哪个函数以及执行到哪里了。
编辑器中的括号匹配。
栈的实现 使用 Java 进行实现。我们将栈定义为一个接口。
1 2 3 4 5 6 7 8 public interface Stack <E> { int getSize () ; boolean isEmpty () ; void push (E e) ; E pop () ; E peek () ; }
数组栈(使用之前实现的动态数组结构):
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 public class ArrayStack <E> implements Stack <E> { private 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(); } public int getCapacity () { return array.getCapacity(); } @Override public void push (E e) { array.addLast(e); } @Override public E pop () { return array.removeLast(); } @Override public E peek () { return array.getLast(); } @Override public String toString () { StringBuilder res = new StringBuilder (); res.append("Stack: " ); res.append('[' ); for (int i = 0 ; i < array.getSize(); i++) { res.append(array.get(i)); if (i != array.getSize() - 1 ) { res.append(", " ); } } res.append("] top" ); return res.toString(); } }
链表栈(会使用之后实现的链表结构):
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 public class LinkedListStack <E> implements Stack <E> { private LinkedList<E> list; public LinkedListStack () { list = new LinkedList <>(); } @Override public int getSize () { return list.getSize(); } @Override public boolean isEmpty () { return list.isEmpty(); } @Override public void push (E e) { list.addFirst(e); } @Override public E pop () { return list.removeFirst(); } @Override public E peek () { return list.getFirst(); } @Override public String toString () { StringBuilder res = new StringBuilder (); res.append("Stack: top " ); res.append(list); return res.toString(); } }