一、中缀式转化为后缀式:(用到一个char型栈和一个数组)

1、遇到数值: 直接存到数组

2、遇到左括号:将左括号入栈

3、遇到右括号:将栈中的运算符依次出栈并存到数组, 直到第一次遇到左括号(该左括号出栈但不存到数组)。至此消除表达式中的一对括号

4、遇到四则运算符:栈中所有优先级大于或等于该四则运算符的运算符依次出栈并存到数组,然后将该运算符入栈

5、字符串遍历结束后如果栈不为空,则依次将操作符弹出并存到数组

 

 

二、后缀式求值:(用到刚得到的那个数组和一个int型栈)

从左到右扫描后缀表达式数组

1、若是操作数,就压栈

2、若是操作符,就连续弹出两个操组数。(先弹出的是第一操作数,后弹出的是第二操作数)

3、栈顶的值即为所需结果

 

 

三、代码

#include <iostream>
#include <stack>
#include <map>
#include <string.h>
#include <stdlib.h>
#include <cstdio>
using namespace std;

string str;     //中序输入串
char temp[100]; //后序逆波兰式
int t = 0;      //后序逆波兰式的有效长度

/**********************************************************/
void change()
{
    stack<char> s; //用栈来临时存储转化过程中的变量

    ///用一个map来存储运算符优先级
    //下标为字符,很有意思
    map<char, int> p;
    p['+'] = p['-'] = 1;
    p['*'] = p['/'] = p['%'] = 2;
    p['@'] = 3; //取反操作,单目运算。优先级最高

    for (int i = 0; str[i] != '\0'; i++)
    {
        ///首先略过空格
        if (str[i] == ' ')
            continue;

        ///遇到左括号
        if (str[i] == '(')
            s.push(str[i]);

        ///遇到右括号
        else if (str[i] == ')')
        {
            while (!s.empty() && s.top() != '(')
            {
                temp[t++] = s.top();
                s.pop();
            }
            s.pop();
        }

        ///遇到操作数。只支持一位整型数或一位字符变量
        else if (str[i] >= '0' && str[i] <= '9' || str[i] >= 'a' && str[i] <= 'z' || str[i] >= 'A' && str[i] <= 'Z')
        {
            temp[t++] = str[i];
        }

        ///遇到运算符
        else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '%' || str[i] == '@')
        {
            while (!s.empty() && p[s.top()] >= p[str[i]])
            {
                temp[t++] = s.top();
                s.pop();
            }
            s.push(str[i]);
        }

        ///遇到非法符号
        else
        {
            cout << "存在非法符号";
            exit(0);
        }
    }

    ///输出剩余的操作符
    while (!s.empty())
    {
        temp[t++] = s.top();
        s.pop();
    }

    //输出得到的后序逆波兰式
    cout << "逆波兰式:" << temp << endl << endl;
}
/**********************************************************/
void calculate()
{
    stack<int> s;

    for (int i = 0; i < t; i++)
    {
        if (temp[i] >= '0' && temp[i] <= '9')
        {
            cout << "入栈:" << temp[i] << " " << endl;
            s.push(temp[i] - '0');
        }
        else if (temp[i] == '@')
        {
            int a = s.top();
            cout << "出栈:" << a << " " << endl;
            s.pop();
            cout << "入栈:" << -a << " " << endl;
            s.push(-a);
        }
        else
        {
            int a = s.top();
            cout << "出栈:" << a << " " << endl;
            s.pop();
            int b = s.top();
            cout << "出栈:" << b << " " << endl;
            s.pop();

            ///注意:a是右边的操作数,b是左边的操作数
            cout << "入栈:" << b << temp[i] << a << " " << endl;
            if (temp[i] == '+')
                s.push(b + a);
            else if (temp[i] == '-')
                s.push(b - a);
            else if (temp[i] == '*')
                s.push(b * a);
            else if (temp[i] == '/')
                s.push(b / a);
            else if (temp[i] == '%')
                s.push(b % a);
            else
            {
                cout << "符号出现错误";
                exit(0);
            }
        }
    }
    cout << endl << "表达式结果:";
    cout << s.top() << endl;
}
/**********************************************************/
int main()
{
    freopen("a.txt", "r", stdin);
    getline(cin, str);

    change(); //中缀式转化为后缀式

    calculate(); //后缀式求值

    return 0;
}

 

  • 输入文件

  • 输出结果

 

多位操作数的版本

请参考:https://blog.csdn.net/coder_dacyuan/article/details/79941743


Solryu
18 声望5 粉丝