6. 基础: 栈

什么是栈

栈可以理解为一个放盘子的架子,盘子一个叠一个放进去,要取的时候只能从最顶上的开始取。后进先出就是典型的栈结构

栈有什么用

作为一个基础的数据结构,一个典型的应用就是函数调用栈。OS给每个线程分配了一块独立的内存空间,这块内存空间被组织成了栈这种结构,用来存储函数调用时的临时变量。每进一个函数,就会将临时变量作为一个栈帧入栈,当函数被调用完成时将这个函数对应的栈帧出栈。

另一个应用场景是表达式求值。如32 + 10 * 200 + 12。 编译器无法像人一样自然而然先算乘法再算加法,计算机中通过两个栈实现,一个保存操作数,一个保存运算符。从左向右遍历表达式,当遇到数字,就直接压入操作数栈,当遇到运算符,就与运算符栈顶元素进行比较。如果栈顶运算符优先级高,就将当前运算符压栈,反之则取运算符栈顶元素以及从操作数栈取两个数做运算,将结果压到操作数栈,继续比较。

如何实现栈

栈是一个操作受限的线性表,只有压栈(push)出栈(pop)取栈顶元素(peek), 判断栈是否为空(isEmpty)等操作。因为本身基础是线性表,而线性表既可以用数组实现,也可以用链表实现。用数组实现的栈是顺序栈用链表实现的栈叫链式栈

以下为使用Java语言实现的顺序栈
package win.elegentjs.algorithms.stack;

/**
 * 演示顺序栈(基于数组的实现)
 */
public class ArrayStackSample {

    public static void main(String[] args) {
        ArrayStack stack = new ArrayStack(10);

        stack.push("a");
        stack.push("b");
        stack.push("c");
        stack.push("d");
        stack.push("e");

        String item = stack.peek();
        System.out.println("栈顶元素是:" + item);

        item = stack.pop();
        System.out.println("出栈元素是:" + item);

        item = stack.peek();
        System.out.println("栈顶元素是:" + item);


    }
}

class ArrayStack {

    private String[] contents;
    private int available;
    private int count;

    public ArrayStack(int available) {
        this.available = available;
        contents = new String[available];
    }

    /**
     * 执行压栈
     */
    public boolean push(String item) {
        if (count == available) {
            return false;
        }

        contents[count++] = item;
        return true;
    }

    /**
     * 执行出栈
     */
    public String pop() {
        if (count == 0) {
            return null;
        }

        return contents[-- count];
    }

    /**
     * 取栈顶元素
     */
    public String peek() {
        if (count == 0) {
            return null;
        }

        return contents[count - 1];
    }


}

// result:
栈顶元素是:e
出栈元素是:e
栈顶元素是:d
分析栈操作时间复杂度

空间复杂度:O(1),因为不需要额外的存储空间,只涉及到个别的变量
时间复杂度
push: O(1)
pop/peek: O(1)

顺序栈 vs 链式栈

数组的最大缺点是两点:
1)初始化后大小固定,无法扩容
2)从中间插入,删除元素会涉及到移位

同时它的优点是存储空间连续,方便随机查找。还有节省空间,不需要存储指向上一个元素和下一个元素的指针。

对应到栈这个数据结构,它的特点是只在栈顶操作,插入和删除都在栈顶,涉及不到中间元素的位移,所以可以避开数组的缺点。所以通常使用数组实现栈即可。当然如果经常对栈的深度不确定,需要频繁扩容的话还是链式栈实现方便,比较链表天生就是无限扩容的。

小结

本章讲解了栈这个基础的数据结构,本质它是一个受限的线性表,只能从一端操作元素,具有先进先出的特点。Java Collection API中使用LinkedList来实现栈。后面分析源码时再详细讲。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值