算术表达式运算栈实现-数据结构-golang

8 篇文章 0 订阅
3 篇文章 0 订阅
本文介绍如何使用Golang构建一个算术表达式运算栈,通过读取字符,将操作数压栈,遇到算符时与栈顶元素比较进行相应运算。运算符的优先级目前通过初始化map来查询,期待优化建议。
摘要由CSDN通过智能技术生成

算术表达式运算栈实现-数据结构-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方便查询,总感觉有点臃肿,望指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值