【數據結構】——中綴表達式求值

題目要求

從鍵盤輸入中綴表達式,創建操做數與運算符堆棧,計算並輸出表達式的求值結果。
基本要求:實現 +, -, *, /四個二元運算符以及();操做數範圍爲0至9。
提升要求:實現+, -兩個一元運算符(即正、負號);操做數可爲任意整型值(程序可不考慮計算溢出)。
若兩個整數相除,結果只保留整數商(餘數丟棄);可不處理表達式語法錯誤。ios

涉及知識點

棧與隊列算法

數據結構設計

採用C++的模板類,分別建立元素類型爲整型的操做數棧OPND和字符型的運算符棧OPTR,每一個棧對象中,elem指針用來創建長度爲n的數組,n表示棧中元素的最大個數,top表示棧頂指針。數組

算法描述

①中綴表達式以'#'結束,'#'字符也作運算符處理。
②'('、')'做爲運算符處理,括號內運算結束後須要消除括號。
③須要創建兩個不一樣類型的棧,整型的操做數棧OPND和字符型的運算符棧OPTR。
④算法主要步驟:
    a. 初始時,OPND置空,'#'做爲OPTR棧底元素;
    b. 依次讀入表達式中的每一個字符,如果操做數,直接壓入OPND棧;
    c. 如果運算符(記爲θ),PTR棧頂運算符(爲λ)優先級;
        λ<θ,θ壓入OPTR棧,繼續讀下一個字符;
        λ=θ,脫括號,繼續讀下一個字符;
        λ>θ,執行λ運算(λ退棧),θ等在棧外(不讀下一個字符),即θ繼續和OPTR 棧頂運算符比較優先級(重複進行以上操做),直至θ能入棧。
⑤對於一元運算符(即正、負號),用'P'表明'+','N'表明'-'。數據結構

程序代碼

#include<iostream>
using namespace std;
template <typename T>
class Stack                 //模板類:棧
{
public:
    Stack();                //默認構造函數
    Stack(int n);           //構造函數,調用函數createStack(int n),建立長度爲n的棧
    ~Stack();               //虛構函數
    int createStack(int n); //建立長度爲n的棧
    int empty();            //判斷棧是否爲空
    int full();             //判斷棧是否爲滿
    int push(T e);          //將元素e壓棧
    int pop(T &e);          //元素出棧,保存在e中
    T get_top();            //獲得棧頂元素
    friend int isoperator(char &e);//判斷字符e是否爲運算符
    friend int isp(char &e);//返回棧中運算符的優先級
    friend int icp(char &e);//返回棧外運算符的優先級
    friend int compute(int x, char a, int y);//求值函數
private:
    T *elem;                //創建長度爲n的數組
    int n;                  //棧中元素的最大個數
    int top;                //棧頂指針
};
template<typename T>
Stack<T>::Stack()
{
    top = -1;
}
template<typename T>
Stack<T>::Stack(int n)
{
    createStack(n);
}
template<typename T>
Stack<T>::~Stack()
{
    n = 0;
    top = -1;
    delete[]elem;
}
template<typename T>
int Stack<T>::createStack(int n)
{
    if (n <= 0)
        return 0;
    this->n = n;
    top = -1;
    elem = new T[n];
    if (!elem)
        return 0;
    return 1;
}
template<typename T>
int Stack<T>::empty()
{
    return top == -1;
}
template<typename T>
int Stack<T>::full()
{
    return top >= n - 1;
}
template<typename T>
int Stack<T>::push(T e)
{
    if (top >= n - 1)
        return 0;
    elem[++top] = e;
    return 1;
}
template<typename T>
int Stack<T>::pop(T & e)
{
    if (top == -1)
        return 0;
    e = elem[top--];
    return 1;
}
template<typename T>
T Stack<T>::get_top()
{
    return elem[top];
};
int isoperator(char &e)        //判斷是否爲運算符
{
    if (e == '+' || e == '-' || e == '*' || e == '/' || e == '(' || e == ')' || e == '#' || e == 'P' || e == 'N')
        return 1;      //是運算符返回1
    else
        return 0;      //不是運算符返回0
}
int isp(char &e)               //返回棧中運算符的優先級
{
    switch (e)
    {
    case '#':
        return 0; break;
    case '(':
        return 1; break;
    case '+':
    case '-':
        return 2; break;
    case '*':
    case '/':
        return 3; break;
    case 'P':
    case 'N':
        return 4; break;
    case ')':
        return 5; break;
    default:
        return -1; break;
    }
}
int icp(char &e)                 //返回棧外運算符的優先級
{
    switch (e)
    {
    case '#':
        return 0; break;
    case ')':
        return 1; break;
    case '+':
    case '-':
        return 2; break;
    case '*':
    case '/':
        return 3; break;
    case 'P':
    case 'N':
        return 4; break;
    case '(':
        return 5; break;
    default:
        return -1; break;
    }
}
int compute(int x, char a, int y)
{
    switch (a)
    {
    case '+':                //計算加法
        return x + y; break;
    case '-':                //計算減法
        return x - y; break;
    case '*':                //計算乘法
        return x * y; break;
    case '/':                //計算除法
        return x / y; break;
    default:
        return -1; break;
    }
}
int g1()
{
    char a, b, c;
    int i, j, f, value, firstOpnd, secondOpnd, m;
    Stack<char> OPTR(MAX);    //創建運算符棧
    Stack<int> OPND(MAX);     //創建操做數棧
    OPTR.push('#');           //'#'壓棧
    cout << "請輸入中綴表達式: ";
    a = getchar();
    while (a != '#' || OPTR.get_top() != '#')
    {
        if (!isoperator(a))   //不是運算符,即爲操做數,操做數入棧
            OPND.push(a - 48);//將字符型轉化爲整型數字
        else                  //是運算符,與棧頂運算符比較優先級大小
        {
            b = OPTR.get_top();//獲得棧頂元素
            i = isp(b);       //棧頂運算符的優先級
            j = icp(a);       //棧外運算符的優先級
            if (i < j)        //棧外運算符優先級高,運算符入棧
                OPTR.push(a);
            else
            {
                OPTR.pop(b);                    
                if (b != '('&&i == j || i > j)
                {
                    c = OPTR.get_top();
                    if ((c == '(' || c == '#') && (b == 'P' || b == 'N'))    /*c爲一元運
                                                                            算符:正負號*/
                    {
                        OPND.pop(firstOpnd); //獲得操做數
                        switch (b)
                        {
                        case 'P':            //正號
                            f = firstOpnd * 1;
                            break;
                        case 'N':            //負號
                            f = firstOpnd * (-1);
                            break;
                        }
                    }
                    else                     //c爲二元運算符
                    {
                        OPND.pop(secondOpnd); //獲得第二操做數
                        OPND.pop(firstOpnd);  //獲得第一操做數
                        f = compute(firstOpnd, b, secondOpnd); //計算求值
                    }
                    OPND.push(f);             //求值結果壓棧
                    continue;
                }
            }
        }
        c = a;
        a = getchar();                         //繼續讀取字符
        while(!isoperator(a) && !isoperator(c))  /*若連續讀取字符均爲數字,則乘以位權
                                                  獲得多位數*/
        {
            OPND.pop(m);
            m = m * 10 + a - 48;
            OPND.push(m);
            c = a;
            a = getchar();
        }
        
    }
    OPND.pop(value);
    return value;      //返回表達式的結果
}
int main()
{
    int a;
    a = g1();
    cout << "運算結果爲:  " << a << endl;
    return 0;
}

示例

(1)程序輸入:3+5*(9-5)/10#
程序輸出:5
1.png函數

(2)程序輸入:P9+10*(N2*8/4)-10#
程序輸出:-41
2.pngthis

(3)程序輸入:20-3*25+(N41/3)*100#
程序輸出:-1355
3.pngspa

相關文章
相關標籤/搜索