Golang栈结构和后缀表达式实现计算器示例
作者:wuYin 发布时间:2024-05-02 16:25:09
标签:Golang,计算器,栈结构,后缀表达式
引言
只进行基本的四则运算,利用栈结构和后缀表达式来计算数学表达式的值。
本文代码:GitHub
运行效果:
问题
如果只能进行两个值的加减乘除,如何编程计算一个数学表达式的值?
比如计算 1+2*3+(4*5+6)*7
,我们知道优先级顺序 ()
大于 * /
大于 + -
,直接计算得 1+6+26*7 = 189
中缀、后缀表达式的计算
人利用中缀表达式计算值
数学表达式的记法分为前缀、中缀和后缀记法,其中中缀就是上边的算术记法: 1+2*3+(4*5+6)*7
,人计算中缀表达式的值:把表达式分为三部分1
2+3
(4*5+6)*7
分别计算值,求和得 189。但这个理解过程在计算机上的实现就复杂了。
计算机利用后缀表达式计算值
中缀表达式 1+2*3+(4*5+6)*7
对应的后缀表达式: 123*+45*6+7*+
,计算机使用栈计算后缀表达式值:
计算后缀表达式的代码实现
func calculate(postfix string) int {
stack := stack.ItemStack{}
fixLen := len(postfix)
for i := 0; i < fixLen; i++ {
nextChar := string(postfix[i])
// 数字:直接压栈
if unicode.IsDigit(rune(postfix[i])) {
stack.Push(nextChar)
} else {
// 操作符:取出两个数字计算值,再将结果压栈
num1, _ := strconv.Atoi(stack.Pop())
num2, _ := strconv.Atoi(stack.Pop())
switch nextChar {
case "+":
stack.Push(strconv.Itoa(num1 + num2))
case "-":
stack.Push(strconv.Itoa(num1 - num2))
case "*":
stack.Push(strconv.Itoa(num1 * num2))
case "/":
stack.Push(strconv.Itoa(num1 / num2))
}
}
}
result, _ := strconv.Atoi(stack.Top())
return result
}
现在只需知道如何将中缀转为后缀,再利用栈计算即可。
中缀表达式转后缀表达式
转换过程
从左到右逐个字符遍历中缀表达式,输出的字符序列即是后缀表达式:
遇到数字直接输出
遇到运算符则判断:
栈顶运算符优先级更低则入栈,更高或相等则直接输出
栈为空、栈顶是
(
直接入栈运算符是
)
则将栈顶运算符全部弹出,直到遇见)
中缀表达式遍历完毕,运算符栈不为空则全部弹出,依次追加到输出
转换的代码实现
// 中缀表达式转后缀表达式
func infix2ToPostfix(exp string) string {
stack := stack.ItemStack{}
postfix := ""
expLen := len(exp)
// 遍历整个表达式
for i := 0; i < expLen; i++ {
char := string(exp[i])
switch char {
case " ":
continue
case "(":
// 左括号直接入栈
stack.Push("(")
case ")":
// 右括号则弹出元素直到遇到左括号
for !stack.IsEmpty() {
preChar := stack.Top()
if preChar == "(" {
stack.Pop() // 弹出 "("
break
}
postfix += preChar
stack.Pop()
}
// 数字则直接输出
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])
}
postfix += digit
i = j - 1 // i 向前跨越一个整数,由于执行了一步多余的 j++,需要减 1
default:
// 操作符:遇到高优先级的运算符,不断弹出,直到遇见更低优先级运算符
for !stack.IsEmpty() {
top := stack.Top()
if top == "(" || isLower(top, char) {
break
}
postfix += top
stack.Pop()
}
// 低优先级的运算符入栈
stack.Push(char)
}
}
// 栈不空则全部输出
for !stack.IsEmpty() {
postfix += stack.Pop()
}
return postfix
}
// 比较运算符栈栈顶 top 和新运算符 newTop 的优先级高低
func isLower(top string, newTop string) bool {
// 注意 a + b + c 的后缀表达式是 ab + c +,不是 abc + +
switch top {
case "+", "-":
if newTop == "*" || newTop == "/" {
return true
}
case "(":
return true
}
return false
}
来源:https://segmentfault.com/a/1190000013126678


猜你喜欢
- Django教程Python下有许多款不同的 Web 框架。Django是重量级选手中最有代表性的一位。许多成功的网站和APP都基于Djan
- 这是一个非常简单的解决方案,柱状图中每一条柱都是一个 div,数据的大小呈现在 div 的宽或高上。 查看演示 例子下载实现的原理
- 一、打开命令提示符方法一:window+R键 ——输入cmd方法二:在此搜索cmd进入命令提示符二、
- 一、前置知识1.1 语料库(Corpus)太长不看版: NLP任务所依赖的语言数据称为语料库。详细介绍版: 语料库(Corpus,复数是Co
- 注:本文的所有数据请移步—— 参考数据一、水平堆叠图堆叠图其实就是柱状图的一种特殊形式fr
- 以下是详细步骤:1、查看磁盘空间情况:[root@localhost backup]# df -h文件系统 &n
- 1、删除目录及目录下所有的文件2、删除目录下的所有文件但目录结构保留3、删除指定文件代码如下/** +-------------------
- windows下载ziplinux下载tar下载地址:https://www.elastic.co/downloads/elasticsea
- Matplotlib 是 Python 的二维绘图库,用于生成符合出版质量或跨平台交互环境的各类图形。图形解析与工作流图形解析 工
- 我们可以把全体人数当作一个集合,想要往其中加入新人有不同的增加方式。可以一周增加一次,也可以集中到月底一起加入集体。我们今天所要讲的在pyt
- 操作方法如下所示:File-->Settings-->Editor-->Color&Fonts-->Lang
- 一般来说,我们判断 iframe 是否加载完成其实与 判断 JavaScript 文件是否加载完成 采用的方法很类似:var&nb
- 前几天网上找了一款 PC 端微信自动清理工具,用了一下,电脑释放了 30GB 的存储空间,而且不会删除文字的聊天记录,很好用,感觉很多人都用
- mysql常用导出数据命令:1.mysql导出整个数据库 mysqldump -hhostname -uusername -pp
- 需求背景最近为公司开发了一套邮件日报程序,邮件一般就是表格,图片,然后就是附件。附件一般都是默认写到txt文件里,但是PM希望邮件里的附件能
- 这个类主要解决在类型转换时,如果直接使用类型转换函数,会因为变量为空或者格式不对而导致程序报错,而这种报错在大多数情况下是允许的.例如要转换
- 一、问题描述最近遇到一个问题,也就是使用分区表进行数据查询/加载的时候比普通表的性能下降了约50%,主要瓶颈出现在CPU,既然是CPU瓶颈理
- 最近做的一个B/S项目,在打印时采用了在IE中嵌入.net winform控件和XML结合的方式(参见http://www.yesky.co
- 一、为图片添加水印 代码如下:<% Dim Jpeg ””//声明变量 Set Jpeg = Server.CreateObject(
- 在之前给大家分享过这篇文章:CentOS 7.0下使用yum安装mysql的方法详解,小编觉得不够详细,今天给大家通过本文给大家做个补充,感