栈
什么是栈?
- 后进者先出,先进者后出,这就是典型的 “ 栈 ” 结构。
- 从栈的操作特性来看,是一种 “ 操作受限 ” 的线性表,只允许在端插入和删除数据。
- 入栈push()和出栈pop()
- 用数组实现的栈叫作顺序栈,用链表实现的栈叫作链式栈.
当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构。
练习题
leetcode 20,155,232,844,224,682,496.
均摊时间复杂度
结: 均摊时间复杂度一般都等于最好情况时间复杂度,因为在大部分情况下,入栈操作的时间复杂度 O 都是 O(1) ,只有在个别时刻才会退化为O(n),所以把耗时多的入栈操作的时间均摊到其他入栈操作上,平均情况下的耗时就接近 O(1)
栈在函数调用中的应用
int main() {
int a = 1;
int ret = 0;
int res = 0;
ret = add(3, 5);
res = a + ret;
printf("%d", res);
reuturn 0;
}
int add(int x, int y) {
int sum = 0;
sum = x + y;
return sum;
}
示例图:
栈在表达式求值中的应用
比如: 34+13*9+44-12/3。
实际上,编译器就是通过两个栈来实现的。其中一个保存操作数的栈,另一个是保存运算符的栈。我们从左向右遍历表达式,当遇到数字,我们就直接压入操作数栈;当遇到运算符,就与运算符栈的栈顶元素进行比较。
-
如果比运算符栈顶元素的优先级高,就将当前运算符压入栈;
-
如果比运算符栈顶元素的优先级低或者相同,从运算符栈中取栈顶运算符,从操作数栈的栈顶取2个操作数,然后进行计算,再把计算完的结果压入操作数栈,继续比较。
如何实现浏览器的前进后退功能?
使用两个栈 X 和 Y ,我们把首次浏览的页面依次压如栈 X ,当点击后退按钮时,再依次从栈 X 中出栈,并将出栈的数据一次放入 Y 栈。当点击前进按钮时 ,我们依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,说明没有页面可以继续后退浏览了。当 Y 栈没有数据,那就说明没有页面可以点击前进浏 览了。
Stack(栈)
特点
- Stack extends Vector
- synchronized,线程安全
- last-in-first-out,后进先出
源码
public class Stack<E> extends Vector<E> {
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);
}
}