計算字符串表達式的值

步驟: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(數字要拼接好) 。

 

 

 

發佈了9 篇原創文章 · 獲贊 26 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章