介绍
栈 (stack) 是限定仅在表尾进行插入或删除操作的线性表。 对栈来说, 表尾端有其 特殊含义, 称为栈顶 (top), 相应地, 表头端称为栈底 (bottom)。 不含元素的空表称为空栈。栈类比生活中的水杯,水从杯口进入,也从杯口出。假如: 栈中有A,B,C,D四个元素,A最先入栈,D最后入栈,如下图所示:
实现原理
栈的操作也是线性表操作,限定从栈顶插入和删除元素,从线性表的角度看,可以从头部插入或者删除,也可以从尾部插入和删除。JDK中Stack继承Vector,实现了入栈出栈方法, 线程安全。
基本操作
入栈操作
public E push(E item) {
addElement(item);
return item;
}
将元素从数组尾部插入
出栈操作
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
出栈在数组末尾删除一个元素,线程安全
查看栈顶元素
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
只是查看栈顶元素值,并不做删除操作
栈是否为空
public boolean empty() {
return size() == 0;
}
根据元素值查询索引
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
栈的应用
栈这种先进后出的特性,非常适合递归操作。
例子: 例用栈将中缀表达式转换为后缀表达式,中缀表达式方便人类的理解,后缀表达式方便计算机的计算。
中缀表达式: a*(b+c/d-e)+f
后缀表达式: abcd/+e-*f+
操作步骤,从头到尾读取中缀表达式的每一个对象,对不同对象按不同的情况处理,具体如下:
-
运算数: 直接输出;
-
左括号: 压入堆栈;
-
右括号: 将栈顶的运算符弹出并输出,直到遇到左括号,出栈,不输出;
-
运算符:
如果优先级大于栈顶运算符时,直接压栈;
如果优先级小于栈顶运算符时,将栈顶运算符弹出并输出,再比对新的栈顶运算符,直到该运算符大于栈顶运算符优先级为止,然后再将该运算符压栈
如果处理完毕,则将栈中运算符全部输出。
实现步骤如下:
步骤 待处理表达式 堆栈状态(底<->顶) 输出状态 1 a*(b+c/d-e)+f 2 *(b+c/d-e)+f a 3 (b+c/d-e)+f * a 4 b+c/d-e)+f *( a 5 +c/d-e)+f *( ab 6 c/d-e)+f *(+ ab 7 /d-e)+f *(+ abc 8 d-e)+f *(+/ abc 9 -e)+f *(+/ abcd 10 e)+f *(- abcd/ 11 )+f *(- abcd/e 12 +f * abcd/e- 13 f + abcd/e-* 14 + abcd/e-*f 15 abcd/e-*f+