php使用逆波兰算法实现四则运算器

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">逆波兰表示法,俗称后缀表示法。</span>

曾经被别人问过,四则运算器的实现,当时仅仅是算的两个数的,周日研究了下四则运算表达式,看到逆波兰算法,从看算法思路到实现并验证花了近2个多小时,怕以后忘掉,所以记录下来,放到工具包中。

逆波兰算法思路,重点是理解大括号的压栈和出栈,这里就不细说了。

有个博客写的不错,入口:http://blog.sina.com.cn/s/blog_3c6889fe0100sb84.html

下面是PHP代码:

<?php
/**
 * Created by PhpStorm.
 * User: lzf
 * Date: 15/6/28
 * Time: 21:40
 */

error_reporting(0);
$expr = '1+(5-6*7)*9';
$expr = '2+45+6/2-45+(23-4)*5';
$expr = '2+45+6/2-20';

//运算符栈,在栈里插入最小优先级的运算符,避免进入不到去运算符比较的循环里
$opArr = array('#');

//运算数栈;
$oprandArr = array();

//运算符优先级
$opLevelArr = array(
    ')' => 2,
    '(' => 3,
    '+' => 4,
    '-' => 4,
    '*' => 5,
    '/' => 5,
    '#' => 1
);

$bolanExprArr = array();

$exprLen = strlen($expr);
$inop = false;
$opNums = "";

//解析表达式
for($i = 0;$i <= $exprLen;$i++){
    $char = $expr[$i];
    //获取当前字符的优先级
    $level = intval($opLevelArr[$char]);
    //如果大于0,表示是运算符,否则是运算数,直接输出
    if($level > 0){
          $inop = true;
          //如果碰到左大括号,直接入栈
          if($level == 3){
              array_push($opArr,$char);continue;
          }

          //与栈顶运算符比较,如果当前运算符优先级小于栈顶运算符,则栈顶运算符弹出,一直到当前运算符优先级不小于栈顶
          while($op = array_pop($opArr)){
              if($op){
                  $currentLevel = intval($opLevelArr[$op]);
                  if($currentLevel == 3 && $level == 2) {
                      break;
                  }elseif($currentLevel >= $level && $currentLevel != 3){
                      array_push($bolanExprArr,$op);
                  }else{
                      array_push($opArr,$op);
                      array_push($opArr,$char);
                      break;
                  }
              }
          }
    }else{
        //多位数拼接成一位数
        $opNums .= $char;
        if($opLevelArr[$expr[$i+1]] > 0){
            array_push($bolanExprArr, $opNums);
            $opNums = "";
        }
    }
}
array_push($bolanExprArr, $opNums);

//输出剩余运算符
while($leftOp = array_pop($opArr)){
    if($leftOp != '#'){
        array_push($bolanExprArr,$leftOp);
    }
}

//计算逆波兰表达式。
foreach($bolanExprArr as $v){
    if(!isset($opLevelArr[$v])){
        array_push($oprandArr,$v);
    }else{
        $op1 = array_pop($oprandArr);
        $op2 = array_pop($oprandArr);

        eval("\$result = $op2 $v $op1;");

        array_push($oprandArr,$result);
    }
}

echo $result;

如有什么错误,请大家批评指证。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值