1. 程式人生 > >(棧)C++中綴表示式轉字尾表示式(可處理多位數字)

(棧)C++中綴表示式轉字尾表示式(可處理多位數字)

題目描述:輸入合法的算術表示式(中綴表示式),輸出原始字串,轉換後的字尾表示式,以及計算結果。

題目考察點:棧的應用,掌握棧先入後出的特點。

演算法思路:中綴表示式轉字尾的演算法採用排程場演算法。當讀入一個數字,就將數字輸出;當讀入一個運算子時,如果此時運算子棧為空就將運算子壓棧,如果運算子棧不為空,就比較當前運算子和棧頂運算子的優先順序,如果當前運算子優先順序大於棧頂運算子,則將當前運算子壓棧,如果優先順序小於等於當前運算子,則將棧頂運算子彈出放至輸出佇列後,繼續比較當前運算子與棧頂運算子優先順序,重複上述過程,直到當前運算子被壓棧。(事實上,這隻針對左結合性的運算子,而加減乘除都是左結合性)。如果有括號,讀到左括號就壓棧,當讀到右括號就將在左括號之後壓棧的所有運算子依次彈出,當然也將左括號彈出。當讀取結束後,棧中還有運算子就將剩餘的運算子依次彈出。此時得到的即為輸出佇列。

在這裡放上一個維基百科的例子。

輸入: 3 + 4 * 2 / ( 1 − 5 ) ^ 2 ^ 3
輸入 動作 輸出 (逆波蘭表示法) 運算子棧 提示
3 將符號加入輸出佇列 3    
+ 將符號壓入操作符堆疊 3 +  
4 將符號加入輸出佇列 3 4 +  
* 將符號壓入操作符堆疊 3 4 * + *號的優先順序高於+號
2 將符號加入輸出佇列 3 4 2 * +  
/ 將堆疊中元素彈出,加入輸出佇列 3 4 2 * + /號和*號優先順序相同
將符號壓入操作符堆疊 3 4 2 * / + /號的優先順序高於+號
( 將符號壓入操作符堆疊 3 4 2 * ( / +  
1 將符號加入輸出佇列 3 4 2 * 1 ( / +  
將符號壓入操作符堆疊 3 4 2 * 1 − ( / +  
5 將符號加入輸出佇列 3 4 2 * 1 5 − ( / +  
) 將堆疊中元素彈出,加入輸出佇列 3 4 2 * 1 5 − ( / + 迴圈直到找到(號
將堆疊元素彈出 3 4 2 * 1 5 − / + 括號匹配結束
^ 將符號壓入操作符堆疊 3 4 2 * 1 5 − ^ / + ^號的優先順序高於/號
2 將符號加入輸出佇列 3 4 2 * 1 5 − 2 ^ / +  
^ 將符號壓入操作符堆疊 3 4 2 * 1 5 − 2 ^ ^ / + ^號為從右至左求值
3 將符號加入輸出佇列 3 4 2 * 1 5 − 2 3 ^ ^ / +  
END 將棧中所有資料加入輸出佇列 3 4 2 * 1 5 − 2 3 ^ ^ / +    

 

至於計算就比較簡單,只需要對字尾表示式進行計算即可。將字尾表示式依次壓棧,讀到數字就壓棧,讀到運算子就從棧中彈出兩個元素做運算,再把結果彈入棧。這裡需要注意的一個問題是,運算時需要用第二個彈出的元素對第一個彈出的元素做運算,比如字尾表示式為21-,此時2壓棧,1壓棧,讀到-號時,先彈出1,再彈出2,則運算2-1.(即次棧頂元素op棧頂元素)

程式碼如下:

#include<iostream>
#include<stack>
#include<string>
#include<cctype>
using namespace std;


bool isNumber(char s)//用於判定是否是數字
{
    if(isdigit(s))
    {
        return true;
    }
    return false;
}

//用數字表示優先順序,把‘+’和‘-’定義為1,‘*’和‘/’定義為2,數字大代表優先順序大
int priorOfOperator(char operator_s)
    {
        int temp = 0;
        if(operator_s == '+'||operator_s == '-')
        {
            temp = 1;
        }
        else if(operator_s == '*' || operator_s == '/')
        {
            temp = 2;
        }
        return temp;
    }

/*處理運算子,遇到運算子比棧頂優先順序高的,則壓棧
否則替代棧頂的運算子,將棧頂運算子加入輸出佇列*/
void handleStackOperator(string& result, char currOper, stack<char>& operators)
{
    if(operators.size() == 0)
    {
       operators.push(currOper);
       return;
    }
    if(priorOfOperator(currOper) > priorOfOperator(operators.top()))
    {
        operators.push(currOper);
    }
    else
    {
        cout<<operators.top();
        result += operators.top();
        operators.pop();
        return handleStackOperator(result, currOper, operators);
    }
}

//有左括號時直接入棧,然後正常操作,遇到右括號時,將左右括號之間所有運算子出棧
void handleOperator(string& result, char currOper, stack<char>& operators)
{
    if(operators.size() == 0)
    {
       operators.push(currOper);
       return;
    }
    if(currOper == '+' || currOper == '-' ||
        currOper == '*' || currOper == '/')
    {
        handleStackOperator(result, currOper, operators);
    }
    else if(currOper == '(')
    {
        operators.push(currOper);
    }
    else if(currOper == ')')
    {
        while(operators.top()!='(')
            {
                cout<<operators.top();
                result += operators.top();
                operators.pop();
            }
            operators.pop();
            return;
    }
}

//計算結果
float caclResult(string& s)
{
    stack<int> result;
    for(int i = 0; i < (int)s.length(); i++)
    {
        if(isNumber(s[i]))
        {
            result.push(s[i] - '0');
        }
        else
        {
            int temp2 = result.top();
            result.pop();
            int temp1 = result.top();
            result.pop();
            if(s[i] == '+')
            {
                result.push(temp1+temp2);
            }
            else if(s[i] == '-')
            {
                result.push(temp1-temp2);
            }
            else if(s[i] == '*')
            {
                result.push(temp1*temp2);
            }
            else if(s[i] == '/')
            {
                result.push(temp1/temp2);
            }
        }
    }
    return result.top();
}

int main()
{
    string test = "";
    string result = "";//用來存字尾表示式,便於最後做計算
    cin>>test;//讀入合法的算術表示式
    cout<<test<<endl;;
    stack<char> test_stack;
    for(int i = 0; i<(int)test.length();i++)
    {
        if(isNumber(test[i]))
        {
            cout<<test[i];
            result += test[i];
        }
        else
        {
            handleOperator(result, test[i],test_stack);
        }
    }
    while(test_stack.size() != 0)//運算子棧不為空則將剩下的全部彈出
   {
       cout<<test_stack.top();
       result += test_stack.top();
       test_stack.pop();
   }
   cout<<endl;
   cout<<caclResult(result)<<endl;//計算結果
    return 0;
}