zoukankan      html  css  js  c++  java
  • 栈及其应用

      栈又称堆栈,是一种运算受限的线性表,其限制是仅允许在表的一端进行插入和删除运算。把对栈进行运算的一端称为栈顶,另一端称为栈底。向一个栈插入新元素称为入栈或进栈,Push;从一个栈删除元素称为退栈或出栈,Pop。因为后进栈的元素必定先出栈,所以又把栈称为后进先出表(Last In First Out, LIFO)。

    栈的应用

      1.输入,之后逆序输出。

      2.语法检查:括号匹配。每当扫描到大中小的左括号后,令其进栈,当扫描到右括号时,则检查栈顶是否为相应的左括号,若是则退栈处理,若不是则出现了语法错误。当扫描到文件结尾,若栈为空则表明没有发现括号配对错误。

      3.数制转换:把十进制的整数转换为二至九之间的任一进制数输出。

      转换方法:要转换为r进制,则原来的数逐次除以基数r(除完之后用商再除),直到商为0,得到的一系列余数的逆序就是转换结果。

    算术表达式的计算

      在中缀表达式(就是我们人类通常写的算术表达式)中,计算需要注意优先级、括号这些问题,和运算符的实际运算次序往往同它们在表达式中的先后次序不一致,所以波兰科学家提出了后缀表达式,把运算符放在两个运算对象的后面。在后缀表达式中看,不存在括号,也不存在运算符优先级的差别,计算过程完全按照运算符出现的先后次序进行,整个计算过程仅需扫描一遍便可完成。

    中缀表达式转换成后缀表达式:

      转换过程如下:从头到尾扫描中缀表达式,若遇到数字则直接写入后缀表达式,若遇到运算符,则比较栈顶元素和该运算符的优先级,当该运算符的优先级大于栈顶元素的时候,表明该运算符的后一个运算对象还没有进入后缀表达式,应该把该运算符暂存于运算符栈中,然后把它的后一个运算对象写入到后缀表达式中,再令其出栈并写入后缀表达式中;若遇到的运算符优先级小于等于栈顶元素的优先级,表明栈顶运算符的两个运算对象已经被写入后缀表达式,应将栈顶元素出栈并写入后缀表达式,对于新的栈顶元素仍进行比较和处理,直到栈顶元素的优先级小于当前等待处理的运算符的优先级为止,然后令该运算符进栈即可。按照上述过程扫描到中缀表达式的末尾,把剩余的运算符依次出栈并写入后缀表达式即可。

      中缀表达式“9+(3-1)*3+10/2”转化为后缀表达式“9 3 1-3*+ 10 2/+”

      下面我们来具体看看这个过程。

      1. 初始化一空栈,用来对符号进出栈使用。

      2. 第一个字符是数字9,输出9,后面是符号“+”,进

      3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。

      4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。

      5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -

      6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。

      7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指 “9+(3-1)*3+”中的最后一个“+”。

      8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。

      9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2

      10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+

    中缀表达式转前缀

      遵循以下步骤:
      (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
      (2) 从右至左扫描中缀表达式;
      (3) 遇到操作数时,将其压入S2;
      (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
        (4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
        (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
        (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
      (5) 遇到括号时:
        (5-1) 如果是右括号“)”,则直接压入S1;
        (5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;
      (6) 重复步骤(2)至(5),直到表达式的最左边;
      (7) 将S1中剩余的运算符依次弹出并压入S2;
      (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
      例如,将中缀表达式“1+((2+3)×4)-5”转换为前缀表达式的过程如下:

      因此结果为“- + 1 × + 2 3 4 5”。

    后缀表达式求值

      从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
      例如后缀表达式“3 4 + 5 × 6 -”:
      (1) 从左至右扫描,将3和4压入堆栈;
      (2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
      (3) 将5入栈;
      (4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
      (5) 将6入栈;
      (6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

    前缀表达式的计算机求值:
      从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 op 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果。
      例如前缀表达式“- × + 3 4 5 6”:
      (1) 从右至左扫描,将6、5、4、3压入堆栈;
      (2) 遇到+运算符,因此弹出3和4(3为栈顶元素,4为次顶元素,注意与后缀表达式做比较),计算出3+4的值,得7,再将7入栈;
      (3) 接下来是×运算符,因此弹出7和5,计算出7×5=35,将35入栈;
      (4) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
      可以看出,用计算机计算前缀表达式的值是很容易的。

  • 相关阅读:
    pgspider sqlite mysql docker 镜像
    pgspider docker 镜像
    pgspider基于pg 的高性能数据可视化sql 集群引擎
    diesel rust orm 框架试用
    golang 条件编译
    Performance Profiling Zeebe
    bazel 学习一 简单java 项目运行
    一个好用node http keeplive agnet
    gox 简单灵活的golang 跨平台编译工具
    mailhog 作为smtp server mock工具
  • 原文地址:https://www.cnblogs.com/wxgblogs/p/5727496.html
Copyright © 2011-2022 走看看