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

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cs湛卢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值