思路:先中缀转后缀,再求值
package main
import(
"fmt"
"unicode"
"strings"
"strconv"
)
// Stack声明
type Stack struct{
top *node
length int
}
type node struct{
value interface{}
prev *node
}
func New()*Stack{
return &Stack{nil,0}
}
func (s *Stack)Len()int{
return s.length
}
func (s *Stack)Peek()interface{}{
if s.length==0{
return nil
}
return s.top.value
}
func (s *Stack)Pop()interface{}{
if s.length==0{
return nil
}
n:=s.top
s.top=n.prev
s.length--
return n.value
}
func (s *Stack)Push(value interface{}){
n:=&node{value,s.top}
s.top=n
s.length++
}
func main(){
var str string
fmt.Scanln(&str)
str=transexp(str)
// fmt.Println(str)
calculate(str)
}
func calculate(exp string){
slice := strings.Split(exp, " ")
// fmt.Println(exp,slice)
explen:=len(slice)
s:=New()
for i:=0;i<explen;i++{
str:=slice[i]
if digit,err:=strconv.Atoi(str);err==nil{
s.Push(digit)
}else{
s1, _ := strconv.Atoi(fmt.Sprintf("%v", s.Pop()))
s2, _ := strconv.Atoi(fmt.Sprintf("%v", s.Pop()))
switch str{
case "+":
s.Push(strconv.Itoa(s1+s2))
case "-":
s.Push(strconv.Itoa(s2-s1))
case "*":
s.Push(strconv.Itoa(s1*s2))
case "/":
if s1!=0{
s.Push(strconv.Itoa(s2/s1))
}
}
}
}
res,_:=strconv.Atoi(fmt.Sprintf("%v", s.Peek()))
fmt.Println(res)
}
func transexp(exp string)string{
opStack:=New()
explen:=len(exp)
res:=""
isNeg:=false
for i:=0;i<explen;i++{
str:=string(exp[i])
switch str{
case "":
continue
case "0","1", "2", "3", "4", "5", "6", "7", "8", "9":
j:=i
digit:=""
for ;j<explen&&unicode.IsDigit(rune(exp[j])); j++ {
digit+=string(exp[j])
}
i=j-1
if isNeg==true{
res+=" "+"-"+digit
isNeg=false
}else{
res+=" "+digit
}
case "(":
opStack.Push(str)
case ")":
for opStack.Len()>0{
preNode:=fmt.Sprintf("%v",opStack.Peek())
if preNode=="("{
opStack.Pop()
break
}
res+=" "+preNode
// res+=preNode
opStack.Pop()
}
default:
// fmt.Println(i,str)
if str=="-"{
if i-1>=0&&(unicode.IsDigit(rune(exp[i-1]))||string(exp[i-1])==")"){
isNeg=false
}else{
isNeg=true
}
}
for opStack.Len()>0{
if isNeg==true{
break
}
top:=fmt.Sprintf("%v",opStack.Peek())
if isPrior(str,top){
break
}
res+=" "+top
// res+=top
opStack.Pop()
}
if !isNeg{
opStack.Push(str)
}
}
}
for opStack.Len() > 0 {
res += fmt.Sprintf(" %v", opStack.Pop())
}
return res
}
func isPrior(op string, top string) bool {
switch top {
case "+", "-":
if op == "*" || op == "/" {
return true
}
case "(":
return true
}
return false
}