开发者学堂课程【Go 语言核心编程 - 数据结构和算法:栈的计算表达式】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/627/detail/9856
栈的计算表达式
内容介绍
一.算法
二.运用
一.算法
1.创建两个栈 numstack, operStack
将一个叫数栈,另一个叫符号栈,进行模拟电脑,假设自己有指针扫描,创建两个站,numstack 存放数,另一个是操作符。
2.numStack 存放数,operstack 操作符
3.index=0
4.exp 计算表达式,是一个字符串
5.开始扫描
如果扫描发现是一个数字,则直接入数栈 numstack ,这个时候栈里面有一个 top 指向的3
6.如果发现是一个运算符。
要考虑符号栈当前的情况,如果符号栈是空栈,运算符则直接入栈,先简化
(1)如果 operStack 是一个空栈,直接入栈
(2)如果 operstack 不是 一个空栈。
(2.1)就要考虑扫描到的运算符的优先级跟这个栈顶那个更高那个更低,如果发现当前operstack栈顶的优先级大于等于当前我准备入栈的运算符的优先级,则从符号栈取出来并从数栈弹出两个数,也就 pop 两个数进行运算,运算的结果从新压入到入栈到数栈,弹了两个数如果已经空了,那就是2先出来,3后出来,2和3并没有删除,数并没有输出。
(2.2)用栈实现一个计算器,首先先把思想弄出来,然后再走代码,如果说没有这个思想,这个代码写出来之后就很难理解,我们针对一个比较简化的东西,先分析思路,表达式的优先级并不清楚,所以说算式对人来说容易,但是对计算机来说就是复杂的,如果发 opertstack 栈顶的运算符的优先级大于等于当前准备入栈的运算符的优先级,就从符号械 pop 出,并从数栈也 pop 两个数,进行运算,运算后的结果再重新入械到数栈,符号再入符号栈。
(2.3)否则,运算符就直接入栈
7.如果扫描表达式完毕,依次从符号械取出符号,然后从数栈取 出两个数,运算后的结果,入数械,直到符号栈为空栈,目前我们发现栈顶的优先级是大于减法的,根据刚才的逻辑,因为是大于等于当前入栈的,把6和2弹出,用一个变量去搜,现在弹到了6和2,紧接着从符号位弹出来,紧接着从星号弹出来,进行运算,运算后等于12,把12入栈到数栈里面去,栈顶走一下,把当前的处理一下,符号入栈。
二.运用
1.实现综合场景器
讲完之后要实际运用一下,用到实际场景里面去,用栈实现一下综合场景器,这个计算器我们也分阶段来实现,首先要把思想整出来,然后写代码,我们针对一个简单的东西,假设三加二是一个表达式,先不用想机器怎么算,先想人怎么算,先乘除后加减,假设不看后面一半,我们是不知道后面怎么处理的,即使给到后面的表达式我们也不知道怎么弄,我们不知道三加二怎么计算,对人来说这个算式容易,可以一眼看出,但是对于计算机来说,不能看出,里面的逻辑,就要去设计算法,我说一下算法,针对这个算式,作两个栈,这两个栈,再设计一个栈,进行运算的时候就是两种运势符号,
2.数栈和符号栈
一种是数算,怎么设计算法是难度,另一个是符号栈,有的地方叫法有差异,我认为有一个指针,开始扫描创建两个栈,一个叫数栈,叫 numstack 另一个叫 operstack ,numstack 是存放数,operstack 操作符,我们把它当做一个指针,初识化给它一个零,他是用来扫描这个式的,我把它取名叫表达式,就是字符串,我们还有一个式,计算表达式,他是一个字符串,我开始扫描,先扫到如果发现是一个数字,直接扔进数栈,如果扫描发现是一个数字,则直接入数栈,一个数,你不知道它会出现什么,那么就先保存,用新的东西放进去,top 指向三,首先是算法,如果发现是运算入栈符,再单查一句话,我们先考虑一个数,先简化,你在做一个东西的时候,先考虑简单的,先考虑具体的三加二,如果符号栈是空栈,这个运算符就直接入空栈,注意如果运算符是空栈,那符号就直接扔进去,直接入栈 第二个问题,如果这个 operstack 不是一个符号栈,如果说加号放进去,满足了,有具体场景比较容易理解,紧接着扫描二是数字直接入数栈,直接进去,大家可以看见结果是正确的,二入栈了,栈指向二,扫描到一个星号,发现是运算符,那operstack 不是空栈,这个时候就要考虑问题,你这个扫描到的运算符的优先级,那个高那个低,如果发现当前这个符号栈的 operstack 栈顶的优先级大于等于当前我准备入栈的运算符的优先级,则要赶快计算,不计算就不行,如果叫小括号中括号就比较麻烦,就从符号栈取出来,pop 出并从数栈弹出两个数,pop 出,进行运算,运算的结构再重新压入到数栈,从二弹出来,三弹出来,二先弹出来,三再弹出来,这两个数还在数里面,这两个二和三还在里面,这个时候还在里面。
3.入栈
星号的运算符还不能弹,当前的运算还低于的,如果发现 operstack 小于否则运算符直接入栈,因为星号的乘法运算级优于加的,我现在把乘号入栈,这个逻辑有点绕,入栈这个地方就指向,继续扫描,如果是数字六入栈,没有可商量,直接入栈,紧接着现在扫描到减号,目前我们发现栈顶的优先级大于减法的,把六和二弹出来,弹出来之后,用变量接收,现在弹出来六和二,紧接着弹的,星号也弹出来,进行运算,运算后等于十二,把十二入栈到里面,十二栈低往下走,当前的符号还没有做处理,所以这个时候符号入栈,入符号栈,这两个逻辑是反过来的,现在再入减法,入到一个位置,把栈低覆盖,走完之后,又继续扫描,扫描到二,满足扫描是数字直接入栈,栈顶覆盖,再扫描已经没有了,就说如果扫描到全部完毕,则应该依次从数栈弹到一个数,进行运算,运算一次入数栈,再弹两个数,再运算,再入栈,最后留在数栈的是最终结果,依次从符号位符号栈,弹出符号,然后从数栈取出两个数进行运算,运算后结果入数栈,直到符号栈为空,直到符号栈为空就结束,现在开始弹东西,弹一个二弹一个其他,又弹了一个二,再紧接着弹一个二和十二,我们一定要知道一定是后面的数对前面的数操作,弹的时候运算的时候,十二减去一个二,这个时候减号弹出来了,这个时候结果是十,把十再入栈,相当于把十覆盖掉,栈顶再覆盖掉,栈顶又上去过后紧接着把十和十三取出来,再把十和三取出来,十取出来就是加法,整个十三做完后一加就自然上去,这个时候只有一个数了,再取就为空了。