学习数据结构--第三章:栈和队列(栈的应用、括号匹配、中后前缀表达式转换)

学习数据结构--第三章:栈和队列(栈的应用、括号匹配、中后前缀表达式转换)

Scroll Down

1.栈的应用

1.1括号匹配

我们在数学运算中 [(A+b)*c] - (E-F) 往往都会有[ ]( ) 来表示运算的优先级,我们把这样的[ ]( ) 提取出来组成的序列叫做括号匹配序列

匹配序列

  • ( [ ( ) ] )
  • [ ] [ ] ( )
  • ( ) [ ( ) ]

上面是正确的可以匹配的序列,每一个( 或者[都有与之对应的)或者]

不匹配序列

  • ( [ ( ) ]
  • ] [ ] ( )
  • ( ] [ ( ) ]

下面是一个正确匹配的序列,我们给每一个标上号,一次输入到栈中,判断阔号是否匹配。

在这里插入图片描述

算法思想:

  • 1.初始化一个空栈,顺序读入阔号
  • 2.若是右阔号,则与栈顶元素进行匹配
    • 若匹配,则弹出栈顶元素进行下一个元素
    • 若不匹配,则该序列不合法
  • 3.若是左阔号,则压入栈中
  • 4.如果全部元素遍历完毕,栈中非空则序列不合法

1.2表达式求值

例如:A+B+C-E-F 像这种简单的表达式求值我们通过遍历,加上if 判断就可以解决,但是[(A+B)*C]-(E-F)这种比较复杂的表达式这就有一些复杂的优先级了。这就需要栈来解决了,下面介绍几种表达式的分类。

在这里插入图片描述

在解决表达式求值的问题我们通常要将中缀表达式转成前缀表达式或者转成后缀表达式,不过最常用的还是转成后缀表达式。常常用后缀表达式计算表达式的值。

1.3中缀表达式转前&后缀

中缀转前缀&后缀

[(A+B)*C]-(E-F)

我们按照运算的优先级首先计算(A+B)讲它转成前缀:+AB,[+AB*C]-(E-F) 接着乘以C转成前缀为:* +ABC,这样第一个方括号的转换完毕,接着按照运算优先级,将[E-F]转成前缀:-EF,现在表达式为:* +ABC-(-EF),接着将中间的-提到最前面得:-*+ABC-EF

前缀表达式:- * + A B C - E F

过程和上面得过程相同,只不过将运算符号号放后面就行。

后缀表达式:A B + C * E F - -

使用栈将中缀转后缀得算法思想:

( ( A + B ) * C ) - ( E - F )

  • 数字直接加入后缀表达式
  • 运算符时:
  • a.若为(,入栈;.b
  • b.若为'),则依次把栈中的运算符加入后缀表达式,直到出现(,并从栈中删除
  • c.若为+,-,*,/
    • 1.栈空,入栈;
    • 2.栈顶元素为(,入栈;
    • 3.高于栈顶元素优先级,入栈;·
    • 4.否则,依次弹出栈顶运算符,直到一个优先级比它低的运算符或(为止;`
  • d.遍历完成,若栈非空依次弹出所有元素。

使用此思想执行一遍将表达式装成后缀:

为了方便文字描述,定义一个H作为后缀表达式,定义一个Z栈。
首先( (依次入栈(规则:a),此时Z=( (,接着数字A,直接加入后缀表达式中此时H=A接着+入栈(规则:c 2),此时Z=*((+接着B直接加入后缀表达式中:H=AB,接着)入栈符合规则b,则此时Z=(,H=AB+,接着*入栈,Z=(*,接着)入栈符合规则b,则此时Z=空H=AB+C*,接着-(依次入栈,此时Z=-(,接着E,直接加入后缀表达式:H=AB+C*E,接着-入栈,此时Z=-(-接着F直接加入后缀表达式中,H=AB+C*EF,接着)入栈符合规则b,则此时z=-,H=AB+C*EF-,然后符合规则d,此时z=空H=AB+C*EF- -

2.递归

递归 若在一个函数、过程或数据结构的定义中又应用了它自身,则称它为递归定义的,简称递归

常见得递归例子:

斐波那契数列:0,1,1,2,3,5......

此数列从第三项开始每一项等于前两项得和。

在这里插入图片描述

使用C实现该递归过程

int Fib(int n){//n是第几个斐波那契数
    if(n==0){
       return 0;
    }else if(n==1){
       return 1;
    }else if(){
       return Fib(n-1)+Fib(n-2);
    }
}

递归得精髓在于能否将原始问题转换为属性相同但规模较小的问题。

2.1递归产生的问题

  • 在递归调用过程中,系统为每一层的返回点、局部变量、传入实参等开辟了递归工作栈来进行数据存储,递归次数过多容易造成栈溢出。
  • 通常情况下递归的效率并不高

比如上述的斐波那契数列函数,假如我们传入5,则整个过程为:

在这里插入图片描述

我们会发现,这当中我们发现一些相同结果我们会重复调用很多遍,这样的重复调用会造成递归的效率不高的问题。

在递归算法转换成非递归算法时,往往需要借助栈来进行。

欢迎关注公众号理木客,坚持原创知识分享,更多精彩等你发现,期待你的关注