借助栈与逆波兰表达式 实现一个计算器,编程语言用的是Golang。
逆波兰表达式可以讲复杂的计算过程转化为简单的 *** 作过程,进而得出答案。 比如 (a+b)*(b-c) 按照逆波兰表达式的规则得到 :ab+bc-*
然后将该表达式的字符以及符号,按照从左到右的顺序,依次入栈,一碰到符号则将栈顶前两个元素取出,做运算然后放入栈内,重复该 *** 作,直到表达式结束。
下面将结合栈与逆波兰表达式写一个简易计算器。
运行命令如下
go run counter.go --Expression=\(3-5\)*4-\(5*8\)/3+78*9
代码示例:
package mainimport ( "fmt" "strconv" "flag")type StackNode struct { Data interface{} next *StackNode}type linkStack struct { top *StackNode Count int}func (this *linkStack) Init() { this.top = nil this.Count = 0}func (this *linkStack) Push(data interface{}) { var node *StackNode = new(StackNode) node.Data = data node.next = this.top this.top = node this.Count++}func (this *linkStack) Pop() interface{} { if this.top == nil { return nil } returnData := this.top.Data this.top = this.top.next this.Count-- return returnData}//Look up the top element in the stack,but not pop.func (this *linkStack) Looktop() interface{} { if this.top == nil { return nil } return this.top.Data}var str *string = flag.String("Expression","","")func main() { flag.Parse() fmt.Println(*str) fmt.Println(Count(*str))}func Count(data string) float64 { //Todo 检查字符串输入 var arr []string = generaterpn(data) return calculaterpn(arr)}func calculaterpn(datas []string) float64 { var stack linkStack stack.Init() for i := 0; i < len(datas); i++ { if isNumberString(datas[i]) { if f,err := strconv.Parsefloat(datas[i],64); err != nil { panic("operatin process go wrong.") } else { stack.Push(f) } } else { p1 := stack.Pop().(float64) p2 := stack.Pop().(float64) p3 := normalCalculate(p2,p1,datas[i]) stack.Push(p3) } } res := stack.Pop().(float64) return res}func normalCalculate(a,b float64,operation string) float64 { switch operation{ case "*": return a * b case "-": return a - b case "+": return a + b case "/": return a / b default: panic("invalID operator") }}func generaterpn(exp string) []string { var stack linkStack stack.Init() var spiltedStr []string = convertToStrings(exp) var datas []string for i := 0; i < len(spiltedStr); i++ { // 遍历每一个字符 tmp := spiltedStr[i] //当前字符 if !isNumberString(tmp) { //是否是数字 // 四种情况入栈 // 1 左括号直接入栈 // 2 栈内为空直接入栈 // 3 栈顶为左括号,直接入栈 // 4 当前元素不为右括号时,在比较栈顶元素与当前元素,如果当前元素大,直接入栈。 if tmp == "(" || stack.Looktop() == nil || stack.Looktop().(string) == "(" || ( compareOperator(tmp,stack.Looktop().(string)) == 1 && tmp != ")" ) { stack.Push(tmp) } else { // ) priority if tmp == ")" { //当前元素为右括号时,提取 *** 作符,直到碰见左括号 for { if pop := stack.Pop().(string); pop == "(" { break } else { datas = append(datas,pop) } } } else { //当前元素为 *** 作符时,不断地与栈顶元素比较直到遇到比自己小的(或者栈空了),然后入栈。 for { pop := stack.Looktop() if pop != nil && compareOperator(tmp,pop.(string)) != 1 { datas = append(datas,stack.Pop().(string)) } else { stack.Push(tmp) break } } } } } else { datas = append(datas,tmp) } } //将栈内剩余的 *** 作符全部d出。 for { if pop := stack.Pop(); pop != nil { datas = append(datas,pop.(string)) } else { break } } return datas}// if return 1,o1 > o2.// if return 0,o1 = 02// if return -1,o1 < o2func compareOperator(o1,o2 string) int { // + - * / var o1Priority int if o1 == "+" || o1 == "-" { o1Priority = 1 } else { o1Priority = 2 } var o2Priority int if o2 == "+" || o2 == "-" { o2Priority = 1 } else { o2Priority = 2 } if o1Priority > o2Priority { return 1 } else if o1Priority == o2Priority { return 0 } else { return -1 }}func isNumberString(o1 string) bool { if o1 == "+" || o1 == "-" || o1 == "*" || o1 == "/" || o1 == "(" || o1 == ")" { return false } else { return true }}func convertToStrings(s string) []string { var strs []string bys := []byte(s) var tmp string for i := 0; i < len(bys); i++ { if !isNumber(bys[i]) { if tmp != "" { strs = append(strs,tmp) tmp = "" } strs = append(strs,string(bys[i])) } else { tmp = tmp+string(bys[i]) } } strs = append(strs,tmp) return strs}func isNumber(o1 byte) bool { if o1 == '+' || o1 == '-' || o1 == '*' || o1 == '/' || o1 == '(' || o1 == ')' { return false } else { return true }}总结
以上是内存溢出为你收集整理的栈_逆波兰表达式_计算器实现_Golang版本全部内容,希望文章能够帮你解决栈_逆波兰表达式_计算器实现_Golang版本所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)