(栈)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;
}

 

猜你喜欢

转载自blog.csdn.net/qq_41448334/article/details/84767973