步驟:1、將表達式轉化成逆波蘭式 2、求逆波蘭式的值
一、將表達式轉化成逆波蘭式
舉個簡單的例子,平常我們寫的數學表達式a+b,就是一種中綴表達式,寫成後綴表達式就是ab+。再舉一個複雜的例子,中綴表達式(a+b)*c-(a+b)/e的逆波蘭式是ab+c*ab+e/-。
(1)首先,需要分配1個棧,用於臨時存儲運算符,此運算符在棧內遵循越往棧頂優先級越高的原則;
(2)從中綴式的左端開始逐個讀取字符x,逐序進行如下步驟:
1.若x是操作數,,將x直接加入ans後邊;
2.若x是運算符,則分情況討論:
若x是'(',則直接壓入棧s;
若x是')',則將距離棧s棧頂的最近的'('之間的運算符,逐個出棧,依次加入ans,此時拋棄'(';
若x是除'('和')'外的運算符,則再分如下情況討論:
若當前棧s的棧頂元素爲'(',則將x直接壓入棧s;
若當前棧s的棧頂元素不爲'(',則將x與棧s的棧頂元素比較,若x的優先級大於棧頂運算符優先級,則將x直接壓入棧s。否者,將棧頂運算符彈出,加入ans,直到棧頂運算符優先級別低於(不包括等於)x的優先級,此時再則將x壓入棧;
【第二步是一個循環,要把中綴式讀完。第三步是在循環之外】
(3)在進行完(2)後,檢查棧是否爲空,若不爲空,則將棧中元素依次彈出並加入ans
(4)完成上述步驟後,ans便爲逆波蘭式輸出結果。
#include<bits/stdc++.h>
using namespace std;
int judge(char data){
int res = 0;
switch (data) {
case '+':
res = 1;
break;
case '-':
res = 1;
break;
case '*':
res = 2;
break;
case '/':
res = 2;
break;
default:
break;
}
return res;
}
string getNiBolan(string str){
string newStr = "";
stack<int> s;
int length =(int)str.length();
for (int i =0 ; i<length; i++) {
char cur = str[i];
if (cur == '(') {
//新元素爲(直接壓棧
s.push(cur);
}
else if(cur ==')')
{
//新元素爲)打印出(上面所有的
if(!s.empty())
{
//棧中有元素
while (!s.empty())
{
char peep = s.top();
s.pop();
if (peep != '(') {
newStr += peep;
}
else
break;
}
}
else
{
//沒有元素遇到(直接報錯
cout<<"the input is error";
exit(1);
}
}
else if ( ('A'<=cur&&cur<='Z')||('a'<=cur && cur<='z')||('0'<=cur && cur<='9') )
{
//新元素爲字符或者數字直接賦值
newStr += cur;
}
else{
//新元素爲+-*/
int curJudge1 = judge(cur);
//當棧不爲空的時候判斷
if (!s.empty())
{
while (!s.empty())
{
char peep = s.top();
//棧頂不爲(
int curJudge2 = judge(peep);
//新元素大於等於棧頂的等級,直接壓棧
if (curJudge1 >= curJudge2)
{
s.push(cur);
break;
}
else
{
//小於就賦值
s.pop();
newStr += peep;
}
}
if(s.empty())
s.push(cur);
}
else
{
//問題2;忘記在空的時候直接壓棧
s.push(cur);
}
}
}
//問題1 忘記了輸出出棧中的所有元素
while (!s.empty()) {
newStr += s.top();
s.pop();
}
return newStr;
}
int main()
{
string s = "(a+b)*c-(a+b)/e";
s = getNiBolan(s);
cout<<s;
return 0;
}
2、求逆波蘭式的值
Example 1:
Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9
Example 2:
Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6
分析:弄一個棧,一個一個讀逆波蘭式,如果是數字就入棧,如果是算符就pop兩個出來計算,再把結果壓棧
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> s;
for(auto a : tokens)
{
if(a.size()==1 && !isdigit(a[0]))
{
int num2 = s.top();
s.pop();
int num1 = s.top();
s.pop();
switch(a[0])
{
case '+':
s.push(num1+num2);break;
case '-':
s.push(num1-num2);break;
case '*':
s.push(num1*num2);break;
case '/':
s.push(num1/num2);break;
}
}
else
{
s.push(atoi(a.c_str()));//c_str()函數返回一個指向正規C字符串的指針, 內容與本string串相同,atoi用於把字符串數字轉爲數字
}
}
return s.top();
}
};
爲了方便程序,我們一般在中綴式轉逆波蘭式的時候,用一個列表裝下每一個token(數字要拼接好) 。