栈的概念和应用

  栈是限定仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的找称为空栈。栈又称为后进先出(Last In First Out)的线性表,简称LIF0结构。

  • 理解桟的定义需要注意:首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。

  定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指找顶,而不是栈底。它的特殊之处就在于限制了这个线性表的插入和删除位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底。栈的插入操作,叫作进栈,也称压栈、入栈。栈的删除操作,叫作出找,也有的叫作弹栈。

  

  应用一》中缀表达式转后缀表达式 

  我们把平时所用的标准四则运算表达式,即“9+(3-1)*3+10/2"叫做中缀表达式。因为所有的运算符号都在两数字的中间,现在我们的问题就是中缀到后缀的转化。

  中缀表达式“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. 将中缀表达式转化为后缀表达式(栈用来进出运算的符号)。
  2. 将后缀表达式进行运算得出结果(栈用来进出运算的数字)。

  整个过程,都充分利用了找的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构。

  应用二.平衡符号

  问题描述: 在编写代码并且编译时,难免会因为少写了一个')'和被编译器报错。也就是说,编译器会去匹配 括号是否匹配。当你输入了一个'(',很自然编译器回去检查你是否有另一个')'符号与之匹配。如果所有的括号都能够成对出现,那么编译器是能够通过的。否则编译器会报错。例如字符序列“(a+b)”是匹配的, 而字符序列"(a+b]"则不是。

  栈的应用:检查每件事情是否能成对出现,算法叙述:做一个空栈。读入字符直到文件结尾。

  1. 如果字符是一个开放符号,则将其推入栈中。

  2. 如果字符是一个封闭符号,则当栈为空时报错。否则,将栈元素弹出。如果弹出的符号不是对应的开放符号,则报错

  3. 在文件结尾,如果栈非空则报错。

  应用三.后缀表达式计算

  为了解释后缀表达式的好处,我们先来看看,计算机如何应用后缀表达式计算出最终的结果20的。后缀表达式:9 3 1-3*+ 10 2/+

  • 规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。

  下面是详细的步骤:

  1. 初始化一个空栈。此桟用来对要运算的数字进出使用。

  2. 后缀表达式中前三个都是数字,所以9、3、1进栈。

  3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。

  4. 接着是数字3进栈。

  5. 后面是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。

  6. 下面是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。

  7. 接着是10与2两数字进栈。

  8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。

  9. 最后一个是符号“+”,所以15与5出找并相加,得到20,将20进栈。

  10. 结果是20出栈,栈变为空。

  • 果然,后缀表达法可以很顺利解决计算的问题。但是我有个疑问,就是这个后缀表达式“9 3 1-3*+ 10 2/+”是如何通过算式“9+(3-1)*3+10/2”变化而来呢?

    后缀转中缀。

原文地址:https://www.cnblogs.com/wxgblogs/p/5467274.html