算术表达式运算栈实现-数据结构-golang
package main
import (
"fmt"
"log"
"strconv"
)
//运算符stack
type opStack []string
//操作数stack
type dataStack []int
//操作符的优先级标识
type priority map[string]map[string]int
var p = make(priority)
func main() {
ops := opStack{}
initPriority()
ops.initOpStack()
ds := dataStack{}
exp := "6/(2*3)#"
r, err := EvalExpression(exp,ops,ds)
if err != nil {
fmt.Println(err)
}
fmt.Println(r)
}
//初始化opStack
func(op *opStack) initOpStack() {
*op = append(*op, "#")
}
//初始化运算符优先级
func initPriority() {
sb_add := make(map[string]int)
sb_add["+"] = 1
sb_add["-"] = 1
sb_add["*"] = -1
sb_add["/"] = -1
sb_add["("] = -1
sb_add[")"] = 1
sb_add["#"] = 1
p["+"]= sb_add
//sb_sub
sb_sub := make(map[string]int)
sb_sub["+"]= 1
sb_sub["-"]= 1
sb_sub["*"]= -1
sb_sub["/"]= -1
sb_sub["("]= -1
sb_sub[")"]= 1
sb_sub["#"]= 1
p["-"] = sb_sub
//sb_mul
sb_mul := make(map[string]int)
sb_mul["+"]= 1
sb_mul["-"]= 1
sb_mul["*"]= 1
sb_mul["/"]= 1
sb_mul["("]= -1
sb_mul[")"]= 1
sb_mul["#"]= 1
p["*"] = sb_mul
//sb_div
sb_div := make(map[string]int)
sb_div["+"] = 1
sb_div["-"] = 1
sb_div["*"] = 1
sb_div["/"] = 1
sb_div["("] = -1
sb_div[")"] = 1
sb_div["#"] = 1
p["/"] = sb_div
//sb_left_bracket
slb := make(map[string]int)
slb["+"] = -1
slb["-"] = -1
slb["/"] = -1
slb["*"] = -1
slb["("] = -1
slb[")"] = 0
p["("] = slb
//sb_right_bracket
srb := make(map[string]int)
srb["+"] = 1
srb["-"] = 1
srb["*"] = 1
srb["/"] = 1
srb[")"] = 1
srb["#"] = 1
p[")"] = srb
//sb_#
sb_shop := make(map[string]int)
sb_shop["+"] = -1
sb_shop["-"] = -1
sb_shop["*"] = -1
sb_shop["/"] = -1
sb_shop["("] = -1
sb_shop["#"] = 0
p["#"] = sb_shop
}
//优先级 1 高 0 相同 -1 底 2 未知操作符
func(op *opStack) Priority(sp string) int {
topOp := (*op)[len(*op)-1]
if t1, ok := p[topOp]; ok {
if r, ok := t1[sp]; ok {
return r
} else {
return 2
}
} else {
return 2
}
}
//向运算符栈插入运算符
func (op *opStack) PushOp(sp string) {
*op = append(*op, sp)
}
//清除运算符栈顶元素
func (op *opStack) PopOp() string {
t := (*op)[len(*op)-1]
*op = (*op)[:len(*op)-1]
return t
}
//向数据栈插入数据
func (sd *dataStack) PushData(i int) {
*sd = append(*sd, i)
}
//清除数据栈顶的元素
func (sd *dataStack) PopData() int {
t := (*sd)[len(*sd)-1]
*sd = (*sd)[:len(*sd)-1]
return t
}
//是否是操作符
func isOp(op string) bool {
switch op {
case "+", "-", "*", "/","(",")","#":
return true
default:
return false
}
}
//执行表达式运算
func execExpresion(a int, op string, b int) int {
switch op {
case "+":
return a + b
case "-":
return a - b
case "*":
return a * b
case "/":
return a / b
default:
return 0
}
}
//表达式运算
func EvalExpression(exp string, ops opStack, ds dataStack) (int, error) {
l := len(exp)
for i:=0; i < l; i++ {
if isOp(string(exp[i])) {
//校验优先级
switch ops.Priority(string(exp[i])) {
case -2:
return 0, nil
case 1:
//栈第一位优先级高
//字符串转整形
b := ds.PopData()
a := ds.PopData()
opex := ops.PopOp()
r := execExpresion(a, opex, b)
ds.PushData(r)
//当前操作符需要和操作符栈进行比对,同优先级需要将栈中的操作符执行出栈操作
if ops.Priority(string(exp[i])) == 0 {
ops.PopOp()
}
case 0:
//同优先级
ops.PopOp()
case -1:
//低优先级
ops.PushOp(string(exp[i]))
}
} else {
//将数据转化成整形
i, err := strconv.Atoi(string(exp[i]))
if err != nil {
log.Fatal(err)
return 0, err
}
ds.PushData(i)
}
}
return ds.PopData(), nil
}
基本思想:
依次读取字符,如果是操作数,入操作数栈,如果是算符则需要和算符栈栈顶元素比较作相应操作。注(#为表达式结束符)
待修正:
运算符优先级目前采取的是初始化方式进行记录,用的是map方便查询,总感觉有点臃肿,望指正