栈(Stack):当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性。
栈是一种操作受限的线性表数据结构,包含两个操作,入栈 push()和出栈 pop(),也就是在栈顶插入一个数据和从栈顶删除一个数据。
用数组实现的栈,我们叫作顺序栈,用链表实现的栈,我们叫作链式栈。
栈的数组实现
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
| public class ArrayStack { private String[] items; private int count; private int n; public ArrayStack(int n) { this.items = new String[n]; this.n = n; this.count = 0; } public boolean push(String item) { if (count == n) return false; items[count] = item; ++count; return true; } public String pop() { if (count == 0) return null; String tmp = items[count-1]; --count; return tmp; } }
|
栈的链表实现
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
| public class StackOfLinked<Item> implements Iterable<Item> { private class Node{ Item item; Node next; } private Node first; private int N; public StackOfLinked(){} public void push(Item item){ Node oldfirst = first; first = new Node(); first.item = item; first.next = oldfirst; N++; } public Item pop(){ Item item = first.item; first = first.next; N--; return item; } public boolean isEmpty(){ return N == 0; } public int size(){ return N; } public Item peek(){ return first.item; }
public Iterator<Item> iterator() { return new LinkedIterator(); }
class LinkedIterator implements Iterator{ int i = N; Node t = first;
public boolean hasNext() { return i > 0; }
public Item next() { Item item = (Item) t.item; t = t.next; i--; return item; } } }
|
应用场景
函数调用栈
操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构, 用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈
栈在表达式求值中的应用
如:34+13*9+44-12/3
两个栈对象,一个存操作数,一个存计算符,遇到运算符,就与运算符栈的栈顶元素进行比较,若比运算符栈顶元素优先级高,就将当前运算符压入栈,若比运算符栈顶元素的优先级低或者相同,从运算符栈中取出栈顶运算符,从操作数栈顶取出2个操作数,然后进行计算,把计算完的结果压入操作数栈,继续比较
栈在括号匹配中的应用
如:{}{()}
用栈保存为匹配的左括号,从左到右一次扫描字符串,当扫描到左括号时,则将其压入栈中;当扫描到右括号时,从栈顶取出一个左括号,如果能匹配上,则继续扫描剩下的字符串。如果扫描过程中,遇到不能配对的右括号,或者栈中没有数据,则说明为非法格式。
当所有的括号都扫描完成之后,如果栈为空,则说明字符串为合法格式;否则,说明未匹配的左括号为非法格式
实现浏览器的前进后退功能
使用两个栈X和Y,我们把首次浏览的页面依次压如栈X,当点击后退按钮时,再依次从栈X中出栈,并将出栈的数据一次放入Y栈。当点击前进按钮时,我们依次从栈Y中取出数据,放入栈X中。当栈X中没有数据时,说明没有页面可以继续后退浏览了。当Y栈没有数据,那就说明没有页面可以点击前进浏览了