四則運算運算式,我們書面使用的叫做中綴運算式,而計算機,卻更加喜歡尾碼表達,括弧優先順序,加減乘除優先順序等使得運算中綴四則運算式變得困難。這個時候引入了一種電腦喜歡的格式,叫做尾碼運算式。本文以PHP代碼,實現中綴運算式轉尾碼運算式的邏輯。
本文以PHP為代碼環境,有人會說進階語言直接寫運算式就好了,它們會算,可是他們為什麼會算,怎麼算的,還是需要把中綴運算式轉為尾碼運算式。因此本文代碼只是類比一個邏輯。
比如:傳統的四則運算運算式(中綴運算式)是9 + ( 3 - 1 ) * 3 + 10 / 2,對應的尾碼運算式就是9 3 1 - 3 * + 10 2 / +。
轉換邏輯:一個字元一個字元的輸入,如果是數字則直接輸出;如果是左括弧則直接入棧;如果是右括弧則開始出棧,直到遇到第一次左括弧為止;如果是加減乘除,則判斷,如果棧頂也是符號,且輸入的符號的優先順序不高於棧頂的符號優先順序,則全部出棧,否則該輸入的符號入棧。
<?php
/**
* 將輸入的字元按照中綴運算式轉尾碼運算式的規則處理
* @param $str 輸入的字元
* @param $stack 棧
* @param $newStrList 新的運算式
*/
function suffix($str, &$stack, &$newStrList){
//如果是數字則輸出
if(is_numeric($str)){
$newStrList .= $str . ' ';
}
//如果是左括弧則入棧
else if($str == '('){
$stack[] = $str;
}
//如果是右括弧則將最近的左括弧之前的所有資料出棧
else if($str == ')'){
while($arrPop = array_pop($stack)){
if($arrPop == '('){
break;
}
$newStrList .= $arrPop . ' ';
}
}
//如果是加減乘除則判斷與棧頂符號優先順序
else if(in_array($str, array('+', '-', '*', '/')) && count($stack) > 0){
$key = (count($stack) - 1);
if(in_array($stack[$key], array('+', '-', '*', '/'))){
//該符號優先順序不高於棧頂符號的
if(checkPriority($str, $stack[$key]) != 1){
for($i=$key; $i>=0; $i--){
if($stack[$i] == '('){
break;
}
$newStrList .= $stack[$i] . ' ';
unset($stack[$i]);
$stack = array_values($stack);
}
}
}
//本次的符號入棧
$stack[] = $str;
}else{
$stack[] = $str;
}
}
/**
* 判斷運算子的優先順序
* @param $operatorA
* @param $operatorB
* @return A大於B返回1,A等於B返回0,A小於B返回-1
*/
function checkPriority($operatorA, $operatorB){
switch($operatorA){
case '+':
case '-':
if($operatorB == '+' || $operatorB == '-'){
return 0;
}else if($operatorB == '*' || $operatorB == '/'){
return -1;
}
break;
case '*':
case '/':
if($operatorB == '+' || $operatorB == '-'){
return 1;
}else if($operatorB == '*' || $operatorB == '/'){
return 0;
}
break;
default:
exit('error');
}
}
//棧
$stack = array();
//待轉換的運算式
$strList = '9 + ( 3 - 1 ) * 3 + 10 / 2';
//新的運算式
$newStrList = '';
$strList = explode(' ', $strList);
foreach($strList as $str){
if($str != ' '){
suffix($str, $stack, $newStrList);
}
}
//數組反轉
while($s = array_pop($stack)){
$newStrList .= $s . ' ';
}
echo $newStrList;