数据结构理论基础——栈

      版权声明:本文为博主原创文章,未经博主允许不得转载。          https://blog.csdn.net/u011815404/article/details/88778203        </div>
        <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
                          <link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-f57960eb32.css">
      <div class="htmledit_views" id="content_views">
        <h1><a name="t0"></a>【概述】</h1>

栈(Stack)是一种特殊的线性表,只能在某一端插入和删除的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶。

由于栈满足先进后出,后进先出的性质,因此也被称为先进后出表(FILO)或后进先出表(LIFO)

当栈中元素个数为零时称为空栈

【栈的逻辑结构】

栈的栈底固定,栈顶浮动,允许进行插入和删除操作的一端称为栈顶(Top),另一端为栈底(Bottom),插入一个元素称为进栈(Push),删除一个栈顶元素称为出栈(Pop)。

无论是顺序栈还是链栈,其出栈、入栈的时间复杂度均为 O(1)

当栈满时再插入元素,将发生上溢,当栈为空时删除元素,将发生下溢。


【栈的顺序存储结构】

1.顺序栈

栈的顺序存储结构即顺序栈,其使用数组来模拟栈,并设置一个栈顶指针 top,选用 a[0] 作为栈底,a[top] 作为栈顶

其元素个数存在限制,并且可能造成空间浪费。

2.双端栈

在一个程序中有时需要同时使用具有相同数据类型的两个栈,当为他们开辟相同的存储空间后,某一时刻一个栈已经满了,而另一个栈还有很大的空间,这样会造成存储空间的浪费,此时可以令两栈共享空间,即使用双端栈

使用一个数组来存储两个栈,让一个栈的栈底为该数组的始端(a[0]),另一个栈的栈底为该数组的末端(a[n-1]),两个栈从各自的端点向中间延伸(top1++,top2--)

由于双端栈的特性,因此其一般是用于具有两栈空间需求存在相反情况时,即一个栈增长,另一个栈缩短的情况。

【栈的逻辑存储结构】

栈的逻辑存储结构即链栈,其将链表的头指针作为栈顶,便于插入、删除操作。

由于其空间是动态扩展的,因此一般不存在上溢的问题,只有当内存没有可用空间时才会出现栈满,但每个元素都需要一个指针域,从而产生了结构性开销。

【实现】

  1. 顺序栈:点击这里
  2. 双端栈:点击这里
  3. 链栈:点击这里

【应用】

1.中缀表达式

中缀表达式:运算符在两个运算对象中间,基本运算符有 +、-、*、/、()、# 等,其中 # 为中缀表达式的界定符

例如:#3*(4+2)/2-5# 就是一个中缀表达式

在进行运算时,要考虑运算符的优先级与结合性,常见运算符优先级表如下:

中缀表达式的求值过程用到两个栈:运算对象栈 Opnd、运算符栈 Optr,算法伪代码如下:

  1. Opnd 初始化为空,Optr 初始化为表达式的界定符 #
  2. 从左到右扫描表达式的每一个字符
    1)若当前字符是操作数:入栈 Opnd
    2)若当前字符是运算符
      ①当前运算符优先级 > 栈 Optr 的栈顶运算符优先级:入栈 Optr,处理下一字符
      ②当前运算符优先级 < 栈 Optr 的栈顶运算符优先级:栈 Opnd 出栈两个操作数,栈 Optr 出栈一个运算符,进行运算后将结果入栈 Opnd,处理当前字符
      ③当前运算符优先级 = 栈 Optr 的栈顶运算符优先级:栈 Optr 栈顶元素出栈,处理下一字符
  3. 当栈 Optr 为空时,输出栈 Opnd 栈顶元素,即为表达式运算结果

以下图为例:

2.中缀表达式转后缀表达式

后缀表达式:所有的计算按照运算符出现的顺序从左向右进行,不用考虑运算符的优先级

例如:中缀表达式 3*(4+2)/2-5 对应后缀表达式 3 4 2 + * 2 / 5 -

为了处理方便,常将中缀表达式转为等价的后缀表达式,在转换过程中用到一个栈 S,算法伪代码如下:

  1. 初始化栈 S
  2. 从左到右依次扫描中缀表达式的每一个字符
    1)若当前字符是操作数:输出该字符,处理下一字符
    2)若当前字符是运算符:
      ①当前运算符优先级 > 栈 S 栈顶运算符优先级:该运算符入栈 S,处理下一字符
      ②当前运算符优先级 < 栈 S 栈顶运算符优先级:栈 S 栈顶运算符弹出并输出,处理当前字符
      ③当前运算符优先级 = 栈 S 栈顶运算符优先级:栈 S 栈顶运算符弹出,处理向下一字符

3.后缀表达式求值

后缀表达式的求值过程中用到一个栈 S,算法伪代码如下:

  1. 初始化栈 S
  2. 从左到右依次扫描表达式的每一个字符
    1)若当前字符是操作数:入栈 S,处理下一个字符
    2)若当前字符是运算符:栈 S 出栈两个操作数,进行运算并将执行结果入栈 S,处理下一个字符
  3. 当表达式的所有字符都处理完成,输出栈顶元素,即为表达式运算结果

以下图为例:

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值