第八章:第15节 PHP数据结构与算法——栈的强化学习(二)

更新于:2017-07-04 21:34:22

紧接着上一节:


如果是“30+2*6-2”,那就出问题了,这是代码中哪里考虑的不周全呢


当运算式是 30+2*6-2 的时候,它这样扫描


1355372439_5252.jpg

现在把30当成 3和0入栈了,把30这一个数当成3和0这两个数来处里了,必然出问题了

现在处理多位数的运算


我们把这段代码:把数字入数字栈

1.png

改成:

1.png

这里有个新的变量$keepNum做字符串运算,需要在while循环前就得先定义好它。

1.png

1.png

1.png

看运算结果:

1.png

1.png

计算正确了。


现在还有需要改进的地方,还没有完美


当碰到运算式:7*2-5*3-3  //14-15-3=-4,又会出错了。

1.png

这不是我们想要的结果


分析为什么会出错呢?


过程:

(1)首先扫描到一个数字7,直接入数栈
(2)继续扫描发现是一个*,现在符号栈是空的,直接入符号栈
(3)继续扫描发现是一个数字2,直接入数栈
(4)继续扫描发现是一个-,现在符号栈不为空,并且-小于当前符号栈栈顶*的运算优先级,则计算。从数栈弹出两个数,从符号栈弹出一个运算符。即从数栈弹出7和2,然后从符号栈弹出*。7*2=14,再把14入数栈,并把-入符号栈
如下图所示:

1355372439_5252.jpg

(5)继续扫描发现是一个数字5,直接入数栈
(6)继续扫描发现是一个*,现在符号栈不为空,*是高于当前符号栈栈顶-的运算优先级,那直接入符号栈
(7)继续扫描发现是一个数字3,直接入数栈
(8)继续扫描发现是一个-,现在符号栈不为空,并且-小于当前符号栈栈顶*的运算优先级,则计算。从数栈弹出两个数,从符号栈弹出一个运算符。即从数栈弹出5和3,然后从符号栈弹出*。5*3=15,再把15入数栈,这个时候就出现问题了
如下图所示:

1355372439_5252.jpg

(9)如果这个时候,你不加控制,就直接把刚才(8)中扫描到的-入栈。

【如果符号栈不为空,就要判读。如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈,然后把当前符号入栈】。

现在再把-入符号栈,而不是让14和15进行运算,就出问题了。
现在把-入符号栈,看出什么问题,看错误的思路会得出什么结果
(10)接着(9)中直接把-入符号栈的思路,继续扫描发现是一个数字3,直接入数栈
如下图所示:

1355372439_5252.jpg

至此扫描完毕
(11)现在开始依次弹出,先从数栈弹出3和15,从符号栈弹出-,计算15-3-->12(为什么是15-3,Stack类的方法getResult($num1,$num2,$oper),$res=$num2-$num1;即用后出栈的数减先出栈的数)。然后把结果12再入数栈
(12)再从数栈弹出12和14,从符号栈弹出-,计算14-12--->2,然后再把结果2入数栈,此时符号栈已经为空了,最终结果为2!!!★很显然这是不对的7*2-5*3-3  //14-15-3=-4,而不是2.


★问题出在哪里了呢?★是(8)中扫描到的-,-要入符号栈,就要先判断在符号栈中是否有和你-相等运算级别的运算符号,而不是直接就入符号栈省去判断的步骤。所以此时的-想入符号栈,就要不停的判断,只要它的优先级小于等于符号栈栈顶的优先级,则数栈和符号栈就一直向下运算,直到它的优先级大于符号栈栈顶的优先级,此时它才能入符号栈。

所以把思路修改如下:
 【如果符号栈不为空,就要判读。如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈,然后把当前符号入栈】。 

改为:

 【如果符号栈不为空,就要判读。如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈,一直到当前符号的运算级别大于符号栈栈顶的优先级,才把当前符号入栈】


代码非常好改,就是把if语句改成while语句

1.png

改成:

1.png

看运算结果正确了

1.png


到此,这个计算器还缺少加上小括号的运算
6*8-(90-78)+60-45
更深一步:6*{8-[(90-78)+60]-45} 如此就相当的复杂了


本节学习代码》》》