[C++]数据结构--栈--中缀表达式求值

本文介绍了如何将中缀表达式转换为后缀表达式并利用栈数据结构进行计算,包括中缀表达式转后缀表达式的规则和C++代码示例,重点讲解了运算符优先级处理和括号的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

示例:

正常表达式:

3*2+15*2-9

后缀表达式:

3 2 * 15 2 * + 9 -

前缀表达式:

- + * 3 2 * 15 2 9

中缀表达式1:

3 * 2 + 15 * 2 - 9

中缀表达式2:

( 3 * 2 ) + ( 15 * 2 ) - 9

 

 

思想:

在掌握后缀表达式求值的基础上,将中缀表达式转换为后缀表达式,调用后缀表达式求值函数,完成计算

后缀表达式求值:[C++]数据结构--栈--后缀表达式求值-优快云博客

前缀表达式求值:[C++]数据结构--栈--前缀表达式求值-优快云博客

 

 

Tips:前缀表达式和后缀表达式中是将操作数入栈,故栈的数据类型设置为double,而中缀表达式是将计算符号入栈,故栈的数据类型变为char 

 

 

中缀→后缀转换过程:

表达式不带有()时:

使用一个字符串接收后缀表达式,对于原本的中缀表达式来说,遇到数字部分正常依次写入字符串,遇到计算符号,若栈为空,入栈。

若栈内有计算符号,则将栈外即将入栈的计算符号B与栈内处于栈顶的计算符号A相比较,如果A的优先级大于B,即A出栈,否则B进栈。

若A出栈后在栈内有新的处于栈顶的计算符号C,则B继续与C比较,直至B入栈。若原本的中缀表达式已经全部扫描完毕,栈中还有未出栈的计算符号时,则计算符号依次出栈

带有()时:

在以上基础规则上,加入()两个符号,对于原本的中缀表达式,遇到(直接入栈。遇到计算符号时,若栈顶为(,正常入栈,其余规则同上。遇到)时,将栈中符号依次弹栈,直到遇见(,这个(也弹栈

 

说明:

1. 支持输入正整数,可输入多数位数字,如15,200等

2.表达式间隔使用空格或,

3.支持加减乘除四种运算

// 中缀表达式求值



/*示例:
正常表达式:
3*2+15*2-9
后缀表达式:
3 2 * 15 2 * + 9 -
前缀表达式:
- + * 3 2 * 15 2 9
中缀表达式1:
3 * 2 + 15 * 2 - 9
中缀表达式2:
( 3 * 2 ) + ( 15 * 2 ) - 9
*/
#include <iostream>
#include <string>
#include <stack>

using namespace std;

// 判断当前字符是否为运算符
bool isoperator(char c)
{
    if (c == '+' || c == '-' || c == '*' || c == '/')
    {
        return true;
    }
    else
    {
        return false;
    }
}

// 判断当前字符是否为数字
bool isnum(char c)
{
    if (c >= '0' && c <= '9')
    {
        return true;
    }
    else
    {
        return false;
    }
}

// 获取运算符运算结果
double performoperator(char op, double num1, double num2)
{
    if (op == '+')
    {
        return num1 + num2;
    }
    else if (op == '-')
    {
        return num1 - num2;
    }
    else if (op == '*')
    {
        return num1 * num2;
    }
    else if (op == '/')
    {
        if (num2 != 0)
        {
            return num1 / num2;
        }
        else
        {
            cout << "除数不能为0" << endl;
            return -1;
        }
    }
    else
    {
        cout << "运算符错误" << endl;
        return -1;
    }
}

// 后缀表达式计算
double postfix(string exp)
{
    int n = exp.length();
    stack<double> S;
    for (int i = 0; i < n; i++)
    {
        if (exp[i] == ' ' || exp[i] == ',')
        {
            continue;
        }
        else if (isnum(exp[i]))
        {
            double operand = 0;

            while (i < exp.length() && isnum(exp[i]))
            {
                operand = (operand * 10) + (exp[i] - '0');
                i++;
            }
            i--;
            S.push(operand);
        }
        else if (isoperator(exp[i]))
        {
            double num2 = S.top();
            S.pop();
            double num1 = S.top();
            S.pop();
            double res = performoperator(exp[i], num1, num2);
            S.push(res);
        }
    }
    return S.top();
}

// 给每个计算符号赋予权重
int weight(char op)
{
    int w = -1;
    switch (op)
    {
    case '+':
        w = 1;
    case '_':
        w = 1;
    case '*':
        w = 2;
    case '/':
        w = 2;
    }
    return w;
}
// 比较两个计算符号的权重等级
bool higher(char c1, char c2)
{
    int w1 = weight(c1);
    int w2 = weight(c2);
    return w1 >= w2;
}


// 将中缀表达式转化为后缀表达式,之后调用后缀表达式求值函数,最终返回表达式结果
// 该函数的返回值是字符串,即后缀表达式格式的字符串
string infix(string exp)
{
    stack<char> C;
    int n = exp.length();
    string postfix_s = ""; // 后缀字符串,初始化为空
    for (int i = 0; i < n; i++)
    {
        if (exp[i] == ' ' || exp[i] == ',') // 遇到空格或,正常输入进后缀字符串,如果这里if条件下的语句中加入continue,则不支持多数位数字输入
        {
            postfix_s = postfix_s + exp[i];
        }
        else if (isoperator(exp[i])) // 遇到计算符号时
        {
            while (!C.empty() && C.top() != '(' && higher(C.top(), exp[i])) // 栈非空且栈顶不为(且栈顶符号优先级高于遇到的中缀字符串中符号优先级
            {
                postfix_s = postfix_s + C.top(); // 弹栈
                C.pop();
            }
            C.push(exp[i]);
        }
        else if (isnum(exp[i])) // 遇到数字,直接输入后缀字符串
        {
            postfix_s = postfix_s + exp[i];
        }
        else if (exp[i] == '(') // 遇到(,直接将(入栈
        {
            C.push(exp[i]);
        }
        else if (exp[i] == ')') // 遇到),将栈中符号依次弹栈,直到遇见(
        {
            while (!C.empty() && C.top() != '(')
            {
                postfix_s = postfix_s + C.top();
                C.pop();
            }
            C.pop();
        }
    }
    // 如果栈中在(之前还有operator,将它们依次弹栈
    while (!C.empty())
    {
        postfix_s = postfix_s + C.top();
        C.pop();
    }
    return postfix_s;
}
int main()
{
    string exp;
    cout << "请输入:";//参考用例3 * 2 + 15 * 2 - 9
                      //正确结果:27
    getline(cin, exp);
    string res = "";
    res = infix(exp);
    cout << "= " << res << endl;
    double rrr = 0;
    rrr = postfix(res);
    cout << "=" << rrr << endl;
    cin.get();
    return 0;
}

参考:

B站搬运的一位印度程序员讲解的视频:栈:中缀到后缀表达式的转换 ( 使用栈来实现 )_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值