栈(Stack)

最近在【极客时间】学习《数据结构和算法》,目的性的梳理以及记录下知识点。

1.理解栈

后进先出,先进后出”,这就是典型的“栈”结构。比如:叠盘子,都是从下往上一个个放;取的时候,我们是从上往下一个个的依次取出来,不能随机抽出,只能按照规则。

从栈的操作特性来看,是一种“操作受限”的线性表。只允许在一端插入和删除数据,基本操作是push(入栈)和pop(出栈),前者是插入元素到栈顶,后者是将栈顶元素删除。

 

2.为什么要用“栈”

事实上,从功能上来说,数组或链表确实可以替换栈,但你要知道,特定的数据结构是对特定场景的抽象,而且,数组或链表暴露了太多的操作接口,操作上的确灵活自由,但使用时就比较不可控,自然就容易出错。

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

3.栈的应用

1)平衡符号:编译器检查程序的语法错误,看看一些符号是否匹配如“([])”是匹配的,而“[(])”是不匹配的;(对应LeetCode的第20题)
2)计算后缀表达式:在输入表达式过程中,遇到操作数就入栈,遇到操作符就从栈中弹出两个操作数进行运算,然后将结果压入栈中,当输入完成后,栈顶即使计算结果
3)中缀表达式转后缀表达:这个涉及运算符的优先级,通过一系列进栈出栈,完成转换
4)函数调用:函数调用的内部实现就是通过栈来完成的

4.如何实现一个“栈”

由于栈是一个表,所以实现表的方法都可以用于实现栈,一种是数组,一种是链表,使用数组需要提前声明一个已知大小的数组,如果声明过大,会造成空间的浪费,所以节省的做法是使用链表。

推荐博客:https://blog.csdn.net/bestsort/article/details/79682164https://blog.csdn.net/jygqm/article/details/80445613

5.栈的时间、空间复杂度

不管是顺序栈还是链式栈,我们存储数据只需要一个大小为n的数组就够了。在入栈和出栈过程中,只需要一两个临时变量存储空间,只需要一两个临时变量存储空间,所以空间复杂度是O(1)。

注意,这里存储数据需要一个大小为n的数组,并不是说空间复杂度就是O(n)。因为,这n个空间是必须的,无法省掉。所以我们说空间复杂度的时候,是指除了原本的数据存储空间外,算法运行还需要额外的存储框架。

6.栈的应用

6.1 函数的参数就是采用栈的方式存储,从右往左入栈,如下:

int test(int a,int b,int c,int d);

参数a到d的地址,从高到低变化,栈的特点是后进先出。在C程序中,栈顶地址大小高于栈底的地址,所以d先入栈,a最后入栈,即C函数的入栈顺序是从右向左。那为什么从右向左呢?

参数入栈顺序是和具体编译器实现相关的。比如,Pascal语言中参数就是从左到右入栈的,有些语言中还可以通过修饰符进行指定,如Visual C++。即然两种方式都可以,为什么C语言要选择从右至左呢?

Pascal语言不支持可变长参数,而C语言支持这种特色,正是这个原因使得C语言函数参数入栈顺序为从右至左。具体原因为:C方式参数入栈 顺序(从右至左)的好处就是可以动态变化参数个数。通过栈堆分析可知,自左向右的入栈方式,最前面的参数被压在栈底。除非知道参数个数,否则是无法通过栈 指针的相对位移求得最左边的参数。这样就变成了左边参数的个数不确定,正好和动态参数个数的方向相反。因此,C语言函数参数采用自右向左的入栈顺序,主要原因是为了支持可变长参数形式。换句话说,如果不支持这个特色,C语言完全和Pascal一样,采用自左向右的参数入栈方式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值