<html>
<head><title>php--计算器的算法实现(二)</title></head>
<body>
<?php
$exp='-3*9-2-1';
echo $exp.'=';
$numStack=new MyStack();
$opeStack=new MyStack();
$index=0;
$keepNum='';
while(true){
$ch=substr($exp,$index,1);
//判断是否是字符
if($opeStack->isOper($ch)){
//是运算符
/**
3.如果发现是运算符
3.1 如果符号栈为空,就直接入符号栈
3.2. 如何符号栈,不为空,就判断
如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算,并把计算结果入数栈.然后把当前符号入栈
3.3 如何符号栈,不为空,就判断
如果当前运算符的优先级大于符号栈顶的这个运算符的优先级,就入栈.
*/
//如何符号栈,不为空,
if($opeStack->isEmpty()==true){
if($ch=='-'){//解决第一字符时操作符‘-’的问题
$numStack->push('0');
$opeStack->push($ch);
}else{
$opeStack->push($ch);
}
}else{
//解决当符号位的优先级最终一致时 比如:3-4*6-2。第二个‘-’能先在3*5 计算完毕之后入栈
while(!$opeStack->isEmpty()&&$opeStack->PRI($ch)<=$opeStack->PRI($opeStack->getTop())){
$num1=$numStack->pop();
$num2=$numStack->pop();
$ope=$opeStack->pop();
$res=$opeStack->getResult($num1,$num2,$ope);
$numStack->push($res);
}
$opeStack->push($ch);
/*
//符号栈不为空
//如果当前运算符的优先级小于等于符号栈顶的这个运算符的优先级,就计算
$chPRI=$opeStack->PRI($ch);
$stackPRI=$opeStack->PRI($opeStack->getTop());
if($chPRI<=$stackPRI){
$num1=$numStack->pop();
$num2=$numStack->pop();
$ope=$opeStack->getTop();
$res=$opeStack->getResult($num1,$num2,$ope);
$numStack->push($res);
// $opeStack->push($ch);
}else{
$opeStack->push($ch);
} */
}//if结束
}else{
$keepNum.=$ch;//解决数字是多位数的问题
//先判断是否到最后,如果到最后就入栈
if ($index==strlen($exp)-1){
$numStack->push($keepNum);
}else{
if($opeStack->isOper(substr($exp,$index+1,1))){
$numStack->push($keepNum);
$keepNum='';
}
}
}
++$index;
if($index==strlen($exp)){
break;
}
}
while(!$opeStack->isEmpty()){
$num1=$numStack->pop();
$num2=$numStack->pop();
$ope=$opeStack->pop();
$res=$opeStack->getResult($num1,$num2,$ope);
$numStack->push($res);
}
echo $numStack->getTop();
class MyStack{
private $top=-1; //模拟栈底,指向-1
private $maxSize=15; //模拟栈的容量为5
private $stack=array();//用来数组来模拟,想数组内填入栈的内容
//判断是否是运算符
public function isOper($ch){
if($ch=='+'||$ch=='-'||$ch=='*'||$ch=='/'){
return true;
}else{
return false;
}
}
//判断栈是否为空
public function isEmpty(){
if($this->top==-1){
return TRUE;
}else{
return FALSE;
}
}
//判断符号的优先级
public function PRI($ch){
if($ch=='*'||$ch=='/'){
return 1;
}else if($ch=='+'||$ch=='-'){
return 0;
}
}
//获得栈顶的值
public function getTop(){
return $this->stack[$this->top];
}
//计算数值
public function getResult($num1,$num2,$ope){
$res=0;
switch($ope){
case '+':
$res=$num1+$num2;
break;
case '-':
$res=$num2-$num1;
break;
case '*':
$res=$num1*$num2;
break;
case '/':
$res=$num2/$num1;
break;
//erqiqu huibohuayuan 155171111 86
}
return $res;
}
//入栈操作
public function push($val){
///先判断栈是否已满
if($this->top==$this->maxSize-1){
echo '栈满,不能添加</br>';
return; //栈满 返回
}
//先top上移,然后填充栈内容
$this->top++;
$this->stack[$this->top]=$val;
}
//出栈
public function pop(){
if($this->top==-1){
echo '栈111空</br>';
return; //空栈,无数据,返回
}
//取出栈顶的数据,同时把该数据返回,别忘了把top指针下移
$topValue=$this->stack[$this->top];
$this->top--;
return $topValue;
}
//显示栈的所有信息
public function showStack(){
if($this->top==-1){
echo '栈空!</br>';
return;//空栈,无数据,返回
}
//结合堆栈的数据结构,是后进先出类型的,因此从栈顶开始,依次往下读出栈的内容
for($i=$this->top;$i>-1;$i--){
echo 'Stack['.$i.']='.$this->stack[$i].'</br>';
}
}
}
?>
</body>
</html>