【資料結構】棧的應用---四則運算表示式求值(中綴表示式與字尾表示式轉換)
用計算機實現帶括號的四則運算的方式。
這裡的困難在於乘除運算的優先順序高於加減運算,並且加入了括號,使得問題變得更加困難。
20世紀50年代,波蘭邏輯學家想到了一種不需要括號的字尾表達法,我們也把它稱為逆波蘭表示。
比如:9+(3-1)*3+10/2
,如果用字尾表示法就是9 3 1 - 3 * + 10 2 / +
,這樣的表示式稱為字尾表示式,叫字尾的原因在於所有的符號都是要在運算數字的後面出現。
字尾表示式的計算方式
為了解釋字尾表示式的好處,我們先來看看,計算機是如何計算字尾表示式的。
字尾表示式9 3 1 - 3 * + 10 2 / +
規則:從左到右遍歷表示式的每個數字和符號,遇到數字就進棧,遇到是符號,就將處於棧頂的兩個數字出棧,進行計算,然後計算結果進棧,一直到最終獲得結果。
果然字尾表示式可以很順利的解決計算問題。那麼這個字尾表示式是怎麼得出來的呢?
中綴表示式轉字尾表示式
我們把平時標準的四則運算表示式比如9+(3-1)*3+10/2
叫做中綴表示式。
中綴表示式:9+(3-1)*3+10/2
轉換字尾表示式: 9 3 1 - 3 * + 10 2 / +
規則:
- 噹噹前字元為數字時,直接輸出;
- 噹噹前字元為”(“時,將其壓棧;
- 噹噹前字元為”)”時,則彈出堆疊中最上的”(“之前的所有運算子並輸出,然後刪除堆疊中的”(” ;
- 噹噹前字元為運算子時,則依次彈出堆疊中優先順序大於等於當前運算子的(到”(“之前為止),輸出,再將當前運算子壓棧;
- 最後彈出所有棧中的內容輸出
程式碼PHP
以下程式碼為本人個人所寫,存在諸多bug,意思點到為止,如有不到之處,敬請指出。
<?php
//將數字項和符號項用空格分隔開
function getItem($str)
{
$arr = [];
$num = "";
for ($i = 0; $i < strlen($str); $i++) {
//如果是個數字,並且不為最後一項
if (is_numeric($str[$i]) && $i != strlen($str) - 1) {
$num .= $str[$i];
} else {
//如果不是個數字,並且num不為空,則放入陣列中
if (!empty($num)) {
$arr[] = $num;
$num = "";
}
//如果是符號,或者最後一項,直接放入陣列中
$arr[] = $str[$i];
}
}
return implode(" ", $arr);
}
//將中綴表示式轉換成字尾表示式
function centerToEnd($str_center)
{
$stack = new \SplStack();
$arr = explode(" ", $str_center);
$arr1 = [];
for ($i = 0; $i < count($arr); $i++) {
if (is_numeric($arr[$i])) {//如果是個數字,直接放入陣列,輸出
$arr1[]= $arr[$i];
}else{
if($arr[$i]=="("){//如果是左括號,則入棧
$stack->push($arr[$i]);
}else if($arr[$i]==")"){//如果是右括號,則彈出堆疊中最上的"("之前的所有運算子並輸出,然後刪除堆疊中的"("
while(true){
$s = $stack->pop();
if($s=="("){
break;
}else{
$arr1[]=$s;
}
}
}else if($arr[$i]=="+"||$arr[$i]=="-"){//噹噹前字元為運算子時,則依次彈出堆疊中優先順序大於等於當前運算子的(到"("之前為止),輸出,再將當前運算子壓棧
while($stack->count()>0){
$s = $stack->pop();
if($s=="("){
break;
}else{
$arr1[]=$s;
}
}
} else if($arr[$i]=="*"||$arr[$i]=="/"){//噹噹前字元為運算子時,則依次彈出堆疊中優先順序大於等於當前運算子的(到"("之前為止),輸出,再將當前運算子壓棧
while($stack->count()>0){
$s = $stack->pop();
if($s=="("){
break;
}else if($s=="+"||$s=="-"){
$stack->push($s);
break;
}else{
$arr1[]=$s;
}
}
}
if($arr[$i]!==")"){//將當前運算子壓入棧
$stack->push($arr[$i]);
}
}
}
//最後彈出棧中的全部內容
while($stack->count()>0){
$arr1[]=$stack->pop();
}
return implode(" ",$arr1);
}
//計算字尾式的和
function sumEnd($str){
$arr = explode(" ", $str);
$stack = new \SplStack();
for ($i = 0; $i < count($arr); $i++) {
if (is_numeric($arr[$i])) {//如果是數字,直接壓入棧中
$stack->push($arr[$i]);
} else {//如果是符號,則彈出棧頂的兩個數,進行運算,然後將運算結果壓入棧中
$n2 = $stack->pop();
$n1 = $stack->pop();
$stack->push(eval("return " . $n1 . $arr[$i] . $n2 . ";"));
}
}
return $stack->pop();//彈出最後結果
}
$str = "9+(3-1)*3+10/2";
//$str = trim(fgets(STDIN));//標準輸入
$str_center = getItem($str);
//echo $str_center;//9 + ( 3 - 1 ) * 3 + 10 / 2
$str_end = centerToEnd($str_center);
//echo $str_end;//9 3 1 - 3 * + 10 2 / +
echo sumEnd($str_end);
相關文章
- 【資料結構與演算法】中綴表示式轉字尾表示式以及字尾表示式的計算資料結構演算法
- 資料結構與演算法——棧(五)中綴表示式轉字尾表示式資料結構演算法
- 【資料結構】棧的應用——中綴表示式求值(c++)資料結構C++
- 算術表示式的字首式、中綴式、字尾式相互轉換
- js實現四則計算(中綴,字尾表示式)JS
- 將中綴表示式轉換為字尾表示式的簡便方法
- 逆波蘭演算法、中綴表示式轉字尾表示式演算法
- 使用棧結構計算中綴表示式
- 棧的應用---字尾表示式
- 資料結構 中綴表示式轉化資料結構
- 棧在表示式求值中的應用
- 教你如何在C++中實現中綴表示式轉字尾表示式C++
- 資料結構學習(C++)——棧應用(表示式求值) (轉)資料結構C++
- 將算數表示式轉換成字尾表示式並計算結果
- 使用棧實現表示式求值,運用棧計算
- 中綴表示式轉為逆波蘭表示式
- C語言- 基礎資料結構和演算法 - 09 棧的應用_中綴表示式轉字尾表示式20220611C語言資料結構演算法
- 計算中綴表示式
- 4、逆波蘭表示式求值——棧(java資料結構)Java資料結構
- 中綴表示式
- 字尾表示式的求值的演算法演算法
- 中綴轉字尾表示式思路分析和程式碼實現
- 表示式計算(棧的應用)
- 【棧】【字串語法】牛牛與字尾表示式字串
- 逆波蘭表示式求值——棧與佇列佇列
- 資訊學奧賽複賽複習09-CSP-J2020-03表示式求值前置知識點-中綴表示式求值、摸運算、模運算性質、棧
- C#資料結構與演算法系列(十):逆波蘭計算器——逆波蘭表示式(字尾表示式)C#資料結構演算法
- python--表示式(運算表示式)Python
- 3.2.5 表示式求值
- 棧的應用——表示式求和
- 表示式計算 用棧完成
- Java表示式求值引擎 - AviatorJava
- 運算子與表示式
- java中運算子與表示式Java
- C#字尾表示式解析計算字串公式C#字串公式
- Java中Lambda表示式的應用Java
- Lambda 表示式的應用
- 中綴表示式的計算,C++版本,Linux環境C++Linux