(重学算法系列)---栈(Stack)

182 阅读2分钟

什么是栈?

  1. 后进者先出,先进者后出,这就是典型的 “ 栈 ” 结构。
  2. 从栈的操作特性来看,是一种 “ 操作受限 ” 的线性表,只允许在端插入和删除数据。
  3. 入栈push()和出栈pop()
  4. 用数组实现的栈叫作顺序栈,用链表实现的栈叫作链式栈.

当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“栈”这种数据结构。

练习题

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);
    }
}