<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;
如有什么错误,请大家批评指证。