1 逆波兰表达式
逆波兰表达式(reverse polish notation,RPN)
1.1 基本概念
逆波兰表达式:后缀表达式
正常表达式:中缀表达式
正常表达式 |
逆波兰表达式 |
a+b |
a,b,+ |
a+(b-c) |
a,b,c,-,+ |
a+(b-c)*d |
a,b,c,-,d,*,+ |
a=1+3 |
a=1,3 + |
http=(smtp+http+telnet)/1024 |
http=smtp,http,telnet,+,+,1024,/ |
1.2 作用
逆波兰表达式作用:将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。我的理解就是不用括号就能决定运算顺序。
这样就能通过入栈和出栈搞定任何普通表达式的运算。如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
逆波兰表达式若以二叉树的形式表示,算子为叶子,算符为根和分枝。
2 逆波兰转换堆栈算法
计算机检索中,一般利用福岛算法对检索表达式进行逆波兰求解。 如(A+B)*(C+D).,则结果为:AB+CD+*.
2.1 堆栈算法流程
定义算子和算符两个栈,它们都是“后进先出表”。算符栈是一个临时堆栈,主要用来重新排列运算符,以便确定运算顺序。算子栈用来存放经过编码后的算子和表达式。一般表达式的处理过程如下:
(1)从左到右逐个扫描提问式的字符,然后予以适当转移。
(2)如果是算子,则将其送入算子栈。
(3)如果是算符,则将其与算符栈栈顶的那个算符按优先级进行比较:若比栈顶运算符优先级高,则把它送入算符栈;若等于或低于栈顶运算符的优先级,则取出栈顶运算符,并从算子栈中弹出两个算子,与栈顶算符一起进行编码,并将编码后的结果入算子栈。接着再将该算符与新的栈顶运算符比较,以此类推。
(4)如果是“(”,则无条件入算子栈。
(5)如果是“)”,则与该“)”相匹配的“(”间的所有运算符都按照后进先出的次序依次从算符栈弹出,并按上述第三条中算符入算子栈的规则入算子栈。
(6)若为表达式的逻辑结束符,则留在算符栈中的运算符按照后进先出的次序依次从算符栈弹出,并按上述第三条中算符入算子栈的规则入算子栈。
最后算子栈中的元素为编码后的表达式。
2.2 堆栈算法分析
假定在检索算式中仅包含“—”(不包含),“ +”( 或) ,“ * ”( 且) ,“( ” ,“ ) ”, “· ”( 结束)运算符。
首先逆波兰表达式中运算符的优先级。设定 “ * ”,“ +”,“ 一” ,“ ( ”, “ ) ”以及 “· ” 的优先级从高到低,取值分别是 3 、2 、2 、l ,l 和 0。
之后分配存储空间,定义所需的变量并初始化。按照前面的数据结构设计,定义一个存储空间:stringSS,字符串变量,作为检索算式存储区;R(N,1 ) ,一维数组,作为 “ 逆波兰式”输出区 ( 这里仅输出字符,不考虑字符类型) 。S( A,2 ) ,二维数组,作为算子栈,其中增加的第 2单元用于存储相应运算符的运算优先级。此外,除 A、N等数组维数变量,还定义了L 、i 、s s 、yxj 、flag等变量,其中,L为 stringSS长度,i 为计数变量初值为 l ,s s为stringSS中截取的每一个字符变量,表示运算符的运算优先级,flag用作标记符,标记前一个字符是否是运算符。
整个流程如下图所示:
该流程为Foxpro程序流程图,有时间会把它改为C程序流程图,但该流程图不影响理解。已经实现,并测试了它的正确性。
3 逆波兰转换二叉树算法
待补充。