开发者学堂课程【Go 语言核心编程 - 数据结构和算法:数据结构和算法—栈的计算表达式(4)】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/627/detail/9859
数据结构和算法—栈的计算表达式(4)
解决多位数的问题
上节最终分析到该表达式涉及到多位数的问题,接下来做一个处理。
需要增加一个逻辑就是处理多位数的问题,解决的核心,如果是一个操作符,if相关的内容没有问题,
主要的问题是在代码:
else{//说明是数
val,_ := strconv.ParseInt(ch, 10, 64)
numStack.Push(int(val))
}
因为上述代码中直接将 ch 做了一个处理
处理多位数的思路:
1.先定义一个变量 keepNum string ,做拼接
2. 怎么判断下面不是一个字符串呢?
需要每次在扫描时都向 index 后面字符测试一下,看看是不是运算符,然后处理。
如果已经到表达式最后,直接将 keepNum 转成指数加入
接下来先定义变量:
在 for 循环上添加代码:
keepNum :=
“”
再在代码上述else{}
的代码中做一个判断,输入:
if index == len(exp) -1{
val,_ := strconv.ParseInt(keepNum,10,64)
numStack.Push(int(val)) //转完后直接压入
}else{
//向 index 后面测试看看是否是运算符 [index]
ifoperStack.IsOper(int([]byte(exp[index+1:index+2])[0])){
//取出 index 后转成 byte 切片,然后取出第0个值,取出后转成 int
//如果是一个操作符,
说明结束,再探运算符就不需要拼接
val,_ := strconv.ParseInt(keepNum,10,64)
numStack.Push(int(val))
keepNum =
“”
//做完后要进行清空,否则会在原先基础上继续进行拼接
}
}
然后注释掉修改代码下的
val,_ := strconv.ParseInt(ch, 10, 64)
numStack.Push(int(val))
总结:
先看是否已经到表达式最后,如果是到最后直接压入是操作符;如果不是到最后,就向后看一位是否是操作符:
如果是操作符就压入,如果不是操作符就继续拼
最后还需要一步如果不是操作符继续拼接的操作:
在 else{}
中的 if 上添加输入:
keepNum +=ch
即说明是数进入到 else 中后先进行拼接,因为 num 原先是空的,先拼接一个,后面是否继续拼接取决于下方的if逻辑。
修改完之后,现在就是要做30+3*6-4
运行一下,结果显示30+3*6-4=44 结果正确
再做一个运算30+30*6-4,看是否正确
运行结果显示30+30*6-4=206正确
再来运算30+30*6-4-6,结果显示30+30*6-4-6=200
基本代码已经完成,但是要想写计算器这种完整的代码,有大括号和小括号的代码,还是比较麻烦,这节讲栈的目的是看运算层怎么运行,和栈的使用场景。
总结笔记:
以上就是对栈的综合计算器运用,主要讲了分析实现的思路
分析实现的思路前节已经讲到,
如下图
1. 创建两个栈,numStack,operStack
2. numStack 存放数,operStack 操作符
3. index :=0
4. exp 计算表达式,是一个字符串
5. 如果扫描发现是一个数字,则直接入 numStack
6. 如果发现是一个运算符。
1) 如果 operStack 是 一个空栈,直接入栈
2) 如果 operStack 不是一个空栈
2.1
如果发现 operStack 栈顶的运算符的优先级大于等于当前准备入栈的运算符的优先级,就从符号栈 pop 出,并从数栈也 pop 两个数,进行运算,运算后的结果再重新入栈到数栈,当前符号再入符
2.2
否则,运算符就直接入栈
7.如果扫描表达式完毕,依次从符号栈取出符号,然后从数栈取出两个数,运算后的结果,入数栈,直到符号栈为空