表示式求值是指給定乙個表示式字串,求得表示式最後的值。
例如給定表示式:3 + 2 * (4 + 1),通過表示式求值後得到的值為13。
這裡之所以寫leetcode是因為做lc中題目時碰到類似題目,所以把這個通用問題寫一寫以作記錄。
這裡只介紹使用棧的版本,其他方法還有待發掘。
其實解決思路是挺明確的,大體是用兩個棧分別儲存操作符和運算元,然後順序解析字串,關鍵在於操作符的操作。這裡分為兩種情況:
操作符的優先順序:如果遇到的操作符優先順序大於棧頂操作符的優先順序,則操作符入棧。
)的問題:如果遇到反括號,則除了遵守優先順序規定外,遇到(要一起消除。
迴圈完成後,根據棧中的內容進行計算,最後得到的數為結果。
注:這裡沒有考慮小數情況(包括除法)和式子中有符號的情況。
雖然程式並不複雜,思路也很直接。但是在實現中需要注意不要使用某個數來代替優先順序,如』『+』的優先順序是1『 等。下面會做詳細說明:
首先來看優先順序表:
priorities[ '+' ][ '-' ] = '>' ;
priorities[ '+' ][ '+' ] = '>' ;
priorities[ '+' ][ '*' ] = '<' ;
priorities[ '+' ][ '/' ] = '<' ;
priorities[ '+' ][ '(' ] = '<' ;
priorities[ '+' ][ ')' ] = '>' ;
priorities[ '-' ][ '-' ] = '>' ;
priorities[ '-' ][ '+' ] = '>' ;
priorities[ '-' ][ '*' ] = '<' ;
priorities[ '-' ][ '/' ] = '<' ;
priorities[ '-' ][ '(' ] = '<' ;
priorities[ '-' ][ ')' ] = '>' ;
priorities[ '*' ][ '-' ] = '>' ;
priorities[ '*' ][ '+' ] = '>' ;
priorities[ '*' ][ '*' ] = '>' ;
priorities[ '*' ][ '/' ] = '>' ;
priorities[ '*' ][ '(' ] = '<' ;
priorities[ '*' ][ ')' ] = '>' ;
priorities[ '/' ][ '-' ] = '>' ;
priorities[ '/' ][ '+' ] = '>' ;
priorities[ '/' ][ '*' ] = '>' ;
priorities[ '/' ][ '/' ] = '>' ;
priorities[ '/' ][ '(' ] = '<' ;
priorities[ '/' ][ ')' ] = '>' ;
priorities[ '(' ][ '+' ] = '<' ;
priorities[ '(' ][ '-' ] = '<' ;
priorities[ '(' ][ '*' ] = '<' ;
priorities[ '(' ][ '/' ] = '<' ;
priorities[ '(' ][ '(' ] = '<' ;
priorities[ '(' ][ ')' ] = '=' ;
可以看到這個優先順序是沒有傳遞性的,例如『(』 和 『+』,對應表中都是』<』。舉個栗子:
棧頂是』(『,遇上『+』,應該將+入棧,則 『+』 > 『(』
棧頂是』+』, 遇上『(』,應該將(入棧,則 『+』 < 『(『
所以用數字來表示優先順序是不合適的。
下面的的**借鑑這個部落格
寫的比較清楚
#include
#include
#include
using
namespace
std ;
// 運算子優先順序表
unordered_map
< char , unordered_map
< char , char > > priorities ;
// 初始化運算子優先順序定義資料
void initpriorities( )
// 計算2個運算元 加減乘除 的結果。
float calculate( float operand1 , float operand2 , char operator )
else
if ( operator == '-' )
else
if ( operator == '*' )
else
if ( operator == '/' )
return ret ;
}// 計算 加減,不帶括號的表示式
float evaluateexpression( const
string& str )
else
if ( ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
ch == '(' || ch == ')' )
// 當前遇到的操作符作為操作符2,將和之前遇到的操作符(作為操作符1)進行優先順序比較
const
char& opt2 = ch ;
for ( ; operators.size( ) > 0 ; )
else
if ( compareret == '<' )
else
if ( compareret == '=' )
} // end for
// 儲存當前遇到操作符,當前操作符還缺少右運算元,要讀完右運算元才能計算。
if ( opt2 != ')' )
lastoperator = opt2 ;
}} // end for
/* 上面的 for 會一面遍歷表示式一面計算,如果可以計算的話。
當遍歷完成後,並不代表整個表示式計算完成了。而會有2種情況:
1.剩餘1個運算子。
2.剩餘2個運算子,且運算子1 小於 運算子2。這種情況,在上面的遍歷過程中是不能進行計算的,所以才會被遺留下來。
到這裡,已經不需要進行優先順序比較了。情況1和情況2,都是迴圈取出最後讀入的操作符進行運算。
*/if ( lastoperator != ')' )
for ( ; operators.size( ) > 0 ; )
return operands[ 0 ] ;
}
Leetcode 逆波蘭表示式求值
解題思路 c 通過乙個棧實現,整體用乙個while迴圈遍歷整個字串,當遇到不能把字元轉換成整型時進行判斷,同時將棧頂兩個元素出棧進行相關運算,運算結果放入棧中繼續進行遍歷。要點 不同資料型別之間的轉換,如果轉換成功則返回true,否則返回false。int.tryparse string s,out...
表示式求值
程式的說明見清華大學出版社 資料結構 c語言版 include include define stack init size 40 define stackincrement 20 define ok 1 define false 0 typedef structs stack typedef st...
表示式求值
既然是表示式求值,自然需要在記憶體中儲存計算結果以及中間值。在 用c語言寫直譯器 一 中提過 變數要求是若型別,而 c 語言中的 view plaincopy to clipboardprint?in basic io.h define memery size 26 typedef enum var...