表達式的求值

   計算中綴表達式是一個特別經典的關於棧的算法題,幾乎全部的數據結構教材中都會涉及,並且不少公司面試或者筆試的時候會把這道題做爲一個考點。所以,他的重要程度就不言而喻,下面 是關於表達式求值的一個總結。ios

 

題目:  輸入一箇中綴表達式計算表達式的結果。c++

輸入的前提假設:面試

                        (1)只考慮+,-,*,/這四種運算符,中綴表達式只有一種括號:()。算法

                        (2)輸入的中綴表達式只有整數,沒有小數。數據結構

                        (3)假定輸入是合法的。spa

 

  爲了按部就班,此處先討論如何將中綴表達式轉化爲後綴表達式,在討論如何計算後最表達式,在前二者的基礎上,討論如何直接計算中綴表達式的結果。對於上面各表達式的概念再也不贅述。.net

一.中綴表達式轉化爲後綴表達式code

      中綴表達式轉化爲後綴表達式式須要一個臨時棧S暫存運算符。blog

首先將各運算符的優先級排列,(數字越大優先級越高):get

1:(

2:+ -

3:* /

4.:)

 

對輸入的中綴表達式從左到右遍歷:

僞代碼:

           (1)若是遇到數字,直接添加到後綴表達式末尾。

           (2)若是遇到+ - * /:

              先判斷棧是否爲空。如果,則將此運算壓入棧。若不是,則查看當前 棧頂元素。若棧頂元素的優先級大於或等於此操做符級別,則彈出棧頂元素,將棧頂元素添加到後綴表達式後面,並繼續上面的判斷。若是不知足上述的判斷,或棧爲空,將這個運算符入棧。

            (3)若是遇到左括號,直接入棧。若是遇到右括號,彈出左括號前的全部操做符,並將左括號彈出。(右括號不如棧)

              (4)字符遍歷結束,若是棧不爲空,則彈出棧中全部的操做符,將他們添加到後綴表達式的末尾,知道棧爲空。

二.計算後綴表達式

僞代碼:            準備一個數字棧,從左到右掃描表達式,若是是數字就入棧。若是是符號,從數字棧中彈出兩個數字,第一個取出的數字爲右運算數,第二個爲左運算數,進行運算。而後將運算結果放入數字棧中,如此反覆直到讀完整個表達式,留在數字棧中的數字就是最終結果。

默認:輸入的表達式中的全部的的數都是0——9的 整數,運算結果也爲整數。

#include<bits/stdc++.h>
using namespace std;
int Get_Priority(char ch)
{
    if(ch=='(') return 1;
    else if(ch=='-'||ch=='+')  return 2;
    else if(ch=='*'||ch=='/')  return 3;
    else return 4;
}

/*     中綴表達式轉後綴表達式     */
string Get_Hou(string s)
{
    stack<char>My_Stack;
    int size=s.size();
    int i=0;
    string res="";///用於保存轉化後的結果
    char temp;
    while(i<size)
    {
        ///若爲數字直接添加到後綴表達式的後面
        if(s[i]>='0'&&s[i]<='9')
        {
            res.push_back(s[i]);
        }
        else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')
        {
            if(My_Stack.empty())///若棧爲空,直接將運算符進棧
            {
                My_Stack.push(s[i]);
            }
            else///否者若棧頂的優先級大於或等於當前的優先級,重複出棧並加入到後綴表達式末尾
            {
                while(!My_Stack.empty())
                {
                  temp=My_Stack.top();
                  if(Get_Priority(temp)>=Get_Priority(s[i]))
                  {
                    res.push_back(temp);
                    My_Stack.pop();
                  }
                  else break;
                }
                My_Stack.push(s[i]);///將當前運算符進棧
            }
        }
        else
        {
            if(s[i]=='(') My_Stack.push(s[i]); ///若爲作左括號直接進棧
           else///不然,將棧中的元素所有出棧知道碰見左括號
           {
             while(My_Stack.top()!='(')
             {
                temp=My_Stack.top();
                res.push_back(temp);
                My_Stack.pop();
             }
              My_Stack.pop();///刪除左括號後綴表達式和前綴表達式不存在括號,位置即體現了優先級
          }
        }
        i++;
    }
    ///遍歷完後若棧非空彈出全部的元素
    while(!My_Stack.empty())
    {
                temp=My_Stack.top();
                res.push_back(temp);
                My_Stack.pop();
    }
    return res;
}

/*      計算後綴表達式         */
int calculate(string s)
{
    stack<int>My_Stack;
    int size=s.size();
    int num1,num2,num3;
    for(int i=0;i<size;i++)
    {
        if(s[i]>='0'&&s[i]<='9')
        {
            My_Stack.push(s[i]-'0');
        }
        else
        {
            num2=My_Stack.top();
            My_Stack.pop();
            num1=My_Stack.top();
            My_Stack.pop();

            switch(s[i])
            {
             case '+':
                   num3=num1+num2;
                   break;
             case '-':
                   num3=num1-num2;
                   break;
             case '*':
                    num3=num1*num2;
                    break;
             case '/':
                    num3=num1/num2;
                    break;
            }
            My_Stack.push(num3);
        }
    }
    return My_Stack.top();
}
int main()
{
    string s="1+(2-3)*4+4/2";
    cout<<"中綴表達式:"<<endl<<s<<endl;
    string res=Get_Hou(s);
    cout<<"後綴表達式:"<<endl<<res<<endl;
    int num_res=calculate(res);
    cout <<"後綴表達式計算結果:"<< endl << num_res << endl;
    return 0;
}

 

參考博客,此段代碼摘自:https://blog.csdn.net/sinat_27908213/article/details/80273557

#include<iostream>
#include<string>
#include<stack>
 
using namespace std;
 
int getPriority(char ch)
{
    //獲取優先級
    if (ch == '(') return 1;
    else if (ch == '+' || ch == '-') return 2;
    else if (ch == '*' || ch == '/') return 3;
    else return 4;
}
 
void calculate(stack<double> &mystack, char operation)
{
    double num1, num2, num3;
    num2 = mystack.top();
    mystack.pop();
    num1 = mystack.top();
    mystack.pop();
    if (operation == '+') {
        num3 = num1 + num2;
    }
    else if (operation == '-') {
        num3 = num1 - num2;
    }
    else if (operation == '*') {
        num3 = num1 * num2;
    }
    else if (operation == '/') {
        num3 = num1 / num2;
    }
 
    mystack.push(num3);
}
 
double calculator(string str)
{
    //計算中綴表達式,默認輸入是合法的
    stack<double> mystack_number;
    stack<char> mystack_operation;
    int i = 0, j;
    int size = str.size();
    char tmp_operation;
    string tmp_num;
    while (i < size) {
        if (str[i] >= '0' && str[i] <= '9') {
            j = i;
            while (j < size && str[j] >= '0' && str[j] <= '9') { j++; }
            tmp_num = str.substr(i, j - i);
            mystack_number.push(atoi(tmp_num.c_str()));
            i = j;
        }
        else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/') {
            if (mystack_operation.empty()) {
                mystack_operation.push(str[i]);
            }
            else {
                while (!mystack_operation.empty()) {
                    tmp_operation = mystack_operation.top();
                    if (getPriority(tmp_operation) >= getPriority(str[i])) {
                        //計算
                        calculate(mystack_number, tmp_operation);
                        mystack_operation.pop();
                    }
                    else break;
                }
                mystack_operation.push(str[i]);
            }
            i++;
        }
        else {
            if (str[i] == '(') mystack_operation.push(str[i]);
            else {
                while (mystack_operation.top() != '(') {
                    tmp_operation = mystack_operation.top();
                    //計算
                    calculate(mystack_number, tmp_operation);
                    mystack_operation.pop();
                }
                mystack_operation.pop();
            }
            i++;
        }
 
    }
    //遍歷完後,若棧非空,彈出全部元素
    while (!mystack_operation.empty()) {
        tmp_operation = mystack_operation.top();
        //計算
        calculate(mystack_number, tmp_operation);
        mystack_operation.pop();
    }
    return mystack_number.top();
}
 
int main()
{
    string str = "1+(2-3)*4+10/2+2*2+2+2/5";
    cout << "中綴表達式爲:" << endl << str << endl;
    double num_res = calculator(str);
    cout << "計算結果:" << endl << num_res << endl;
    system("pause");
    return 0;
}
相關文章
相關標籤/搜索