package datastructure.stack
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
object PolandNotation {
def main(args: Array[String]): Unit = {
val exp_ = "10+((20+30)*40)-50"
val expArr = toInfixArr(exp_)
println("前缀表达式为:"+expArr.mkString(" "))
val suffixArr = parseInfix2Suffix(expArr)
println("后缀表达式为:"+suffixArr.mkString(" "))
//思路
//1.将exp表达式放到List中
//2.将传给一个方法配合栈,完成计算
println("res="+calculate(suffixArr))
}
/**
* 计算后缀表达式
* @param arr 后缀表达式
* @return
*/
def calculate(arr: Array[String]): Int = {
val stack = new mutable.Stack[String]
var res = 0
arr.foreach(
item=>{
if(item.matches("\\d+")){//多位数入栈
stack.push(item)
} else {//pop 出两个数并运算在入栈
val num1 = stack.pop().toInt
val num2 = stack.pop().toInt
item match {
case "+" => res = num1+num2
case "-" => res = num2-num1
case "*" => res = num1*num2
case "/" => res = num2/num1
case _ => throw new RuntimeException("运算符有问题")
}
stack.push(res.toString)
}
}
)
//最后留在stack中的数据就是结果
stack.pop().toInt
}
/**
* 中缀表达式转成arr
* @param exp 中缀表达式
* @return
*/
def toInfixArr(exp: String) : Array[String] = {
val exp_ = exp.replaceAll("\\s+", "")
var i = 0 //遍历中缀字符串的下标
var str = "" //多位数拼接
val list = new ArrayBuffer[String]()
var c = '0'
do {
//如果是一个非数字,加入到list
c = exp_.charAt(i)
if( c < 48 || c > 57){
list.append(c.toString)
i += 1
} else {//如果是数需要考虑多位数
str = ""
while (i < exp_.length() && c >= 48 && c <= 57){
str += c
i += 1
if (i < exp_.length) c = exp_.charAt(i)
}
list.append(str)
}
}while(i < exp_.length)
list.toArray
}
/**
* 1) 初始化一个栈和List:运算符栈 s1 和储存中间结果的List s2;
* 2) 从左至右扫描中缀表达式;
* 3) 遇到操作数时,将其压 s2;
* 4) 遇到运算符时,比较其与 s1 栈顶运算符的优先级:
* 1.如果 s1 为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
* 2.否则,若优先级比栈顶运算符的高,也将运算符压入 s1;
* 3.否则,将 s1 栈顶的运算符弹出并压入到 s2 中,再次转到(4-1)与 s1 中新的栈顶运算符相比较;
* 5) 遇到括号时:
* 1.如果是左括号“(”,则直接压入 s1
* 2.如果是右括号“)”,则依次弹出 s1 栈顶的运算符,并压入 s2,直到遇到左括号为止,此时将这一对括号丢弃
* 6) 重复步骤 2 至 5,直到表达式的最右边
* 7) 将 s1 中剩余的运算符依次弹出并压入 s2
* 8) 依次弹出 s2 中的元素并输出,结果的逆序(栈)即为中缀表达式对应的后缀表达式
*
* 注意:栈s2是做存储作用,一直没有弹栈,可用list替换直接输出list
*/
def parseInfix2Suffix(infix: Array[String]): Array[String] = {
//(3 + 4) * 5 - 6
val s1 = new mutable.Stack[String]
val s2 = new ArrayBuffer[String]
infix.foreach(item=>{
if(item.matches("\\d+")){
//数直接入栈
s2.append(item)
} else if(item.equals("(")){
//如果是左括号“(”,则直接压入 s1
s1.push(item)
} else if(item.equals(")")){
//如果是右括号“)”,则依次弹出 s1 栈顶的运算符,并压入 s2,直到遇到左括号为止,此时将这一对括号丢弃
while (!s1.top.equals("(")){
s2.append(s1.pop())
}
s1.pop()//将小括号弹出消除一对括号
} else {
//当 item 的优先级小于等于s1栈顶运算符, 将s1栈顶的运算符弹出并加入到 s2 中,再次转到(4.1)与 s1 中新的栈顶运算符相比较
while (s1.nonEmpty && getPri(s1.top) > getPri(item) ){
s2.append(s1.pop())
}
//将item压入栈中
s1.push(item)
}
})
//将 s1 中剩余的运算符依次弹出并压入 s2
while (s1.nonEmpty){
s2.append(s1.pop())
}
s2.toArray
}
def getPri(oper: String): Int = {
oper match {
case "+" => 1
case "-" => 1
case "*" => 2
case "/" => 2
case _ =>
// println(s"不存在该运算符:$oper")
0
}
}
}
前缀表达式转后缀表达式-->逆波兰计算器
最新推荐文章于 2022-05-01 21:53:13 发布