昨天发了一个面试题:关于一道面试题【字符串 ‘1 + (5 - 2) * 3’,怎么算出结果为10,’eval’除外】,受到了各位大大的指点,用一个比较简单的解法就能够计算出来,因此自己在下班后按照各位的指点又实现了一遍,这里贴出来供大家参考。
了解前缀、中缀、后缀表达式
关于概念这里简单贴一下,想了解更多的可以自行Google
- 前缀表达式:是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面。为纪念其发明者波兰数学家Jan Lukasiewicz,前缀表达式也称为“波兰式”。例如,- 1 + 2 3,它等价于1-(2+3)。
- 中缀表达式:是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4),中缀表达式是人们常用的算术表示方法。
- 后缀表达式:指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行,后缀表达式也称为“逆波兰式”。例如:1 2 3 4 + * + 5 +
注: 与前缀表达式(例:+ 3 4)或后缀表达式(例:3 4 +)相比,中缀表达式不容易被计算机解析,但仍被许多程序语言使用,因为它符合人们的普遍用法。
中缀表达式如何转换为后缀表达式以及运算
一、 将中缀表达式转换成后缀表达式算法:
- 从左至右扫描一中缀表达式。
- 若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
- 若读取的是运算符
- 该运算符为左括号”(“,则直接存入运算符堆栈。
- 该运算符为右括号”)”,则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。
- 该运算符为非括号运算符:
- 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。
- 若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。
- 若比运算符堆栈栈顶的运算符优先级低或者优先级相等,则输出栈顶运算符到操作数堆栈,直到比运算符堆栈栈顶的运算符优先级低或者为空时才将当前运算符压入运算符堆栈。
- 当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。
二、逆波兰表达式求值算法:
- 循环扫描语法单元的项目。
- 如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。
- 如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。
- 如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。
- 将运算结果重新压入堆栈。
- 重复步骤2-5,堆栈中即为结果值。
看上面的概念我都看晕了,接下来以一个例子讲解:
1 + 2 * (3 + 4) + 5
originArr 代表字符串转化为数组之后的数组
operatorArr 代表运算符数组
reverseArr 代表后缀表达式数组
下面是一步一步的过程
originArr: ["1","+","2","*","(","3","+","4",")","+","5"]
operatorArr: []
reverseArr: ["1"]
operatorArr: ["+"]
reverseArr: ["1"]
operatorArr: ["+"]
reverseArr: ["1","2"]
operatorArr: ["+","*"]
reverseArr: ["1","2"]
operatorArr: ["+","*","("]
reverseArr: ["1","2"]
operatorArr: [