数据结构-栈与队列--中缀转为后缀表达式

问题分析

什么后缀表达式

  • 我们平时使用的为中缀表达式,操作符在两个操作数之间,而所谓后缀表达式,即操作符在两个操作数之后
  • 比如中缀表达式A\times B/C变成后缀表达式AB\times C/

为什么要使用后缀表达式

  • 在我们的认知中,我们接触一般都是中缀表达式,例如:A+BA/B-C+D\times E-A\times C等;
  • 但在计算机中,如果是像A+B这样简单的计算不用太多思考,但对于像A/B-C+D\times E-A\times C这样甚至还要稍复杂的表达式,我们要考虑到计算符优先级的问题,将其转为((((A/B)-C)+(D\times E))-(A\times C))才能进行计算;
  • 尤其涉及到计算符优先级的表达式时,如果直接计算中缀表达式就显得有些复杂了,这里我可以将其转换为后缀表达式进行计算,以A/B-C+D\times E-A\times C为例:
中缀 后缀
A/B-C+D\times E-A\times C AB/C-DE\times +AC\times -
  • AB/C-DE\times +AC\times -计算过程如下:
操作 后缀表达式
T_1=A/b T_1C-DE\times +AC\times -
T_2=T_1-C T_2DE\times +AC\times -
T_3=D\times E T_2T_3+AC\times -
T_4=T_2+T_3 T_4AC\times -
T_5=A\times C T_4T_5-
T_6=T_4-T_5 T_6

实现方法

  • 我们应该先了解各种操作符的优先级
优先级 操作符
1 一目减(负号),!
2 *,/,%
3 =,-
4 <,<=,>,>=
5 ==,!=
6 且
7 或
  • 我们可以用数据机构-栈来存储操作符,以表达式A\times (B+C)\times D为例 ,过程如下表:
标记 堆栈 输出 备注
A 空 A
\times \times A 栈为空,入栈
( \times( A 括号开始,入栈
B \times( AB
+ \times(+ AB 括号未结束,入栈
C \times(+ ABC
) \times ABC+ 括号结束,符号出栈
\times \times ABC+\times 都为乘号,优先级相同,出栈,新乘号入栈
D \times ABC+\times D
空 空 ABC+\times D\times 表达式结束,全部出栈
  • 在栈中栈顶元素与将要入栈的操作符(不包括括号或者停位符#)优先级进行比较,优先级高就先输出

  • 以下代码以+-\times /表达式为例

操作符优先级获取

  • 这里直接上代码
//判断是否为运算符
bool is_operator(const char temp)
{
    return temp == '+' || temp == '-' || temp == '/' || temp == '*' || temp == '(' || temp == ')';
}

//得到运算符优先级
int level_operator(char temp)
{
    if (temp == '+' || temp == '-')return 2;
    else if (temp == '*' || temp == '/')return 1;
    else return 0;
}

中缀转后缀表达式

  • 这里的函数没有返回结果,而是在函数中直接输出,代码如下:
//中缀转后缀
//中缀转后缀
void Infix_convert(string ex)
{
    //得到表达式长度
    int length = ex.size();
    stack<char>op;
    //防止栈空出错
    op.push('#');

    for (int i = 0; i < length; i++)
    {
        if (!is_operator(ex[i]))cout << ex[i];
        else if (ex[i] == ')')
        {
            for (; op.top() != '('; op.pop())
            {
                cout << op.top();
            }
            op.pop();
        }
        else
        {
            for (; level_operator(op.top()) <= level_operator(ex[i])&&op.top()!='#'&&op.top()!='('; op.pop())
            {
                cout << op.top();
            }
            op.push(ex[i]);
        }
    }
    //将栈中的剩余操作符输出
    while (op.top() != '#')
    {
        cout << op.top();
        op.pop();
    }
    cout << endl;
}

代码总览

#include<iostream>
#include<stack>
#include<string>
using namespace std;

//判断是否为运算符
bool is_operator(const char temp)
{
    return temp == '+' || temp == '-' || temp == '/' || temp == '*' || temp == '(' || temp == ')';
}

//得到运算符优先级
int level_operator(char temp)
{
    if (temp == '+' || temp == '-')return 2;
    else if (temp == '*' || temp == '/')return 1;
    else return 0;
}

//中缀转后缀
void Infix_convert(string ex)
{
    //得到表达式长度
    int length = ex.size();
    stack<char>op;
    //防止栈空出错
    op.push('#');

    for (int i = 0; i < length; i++)
    {
        if (!is_operator(ex[i]))cout << ex[i];
        else if (ex[i] == ')')
        {
            for (; op.top() != '('; op.pop())
            {
                cout << op.top();
            }
            op.pop();
        }
        else
        {
            for (; level_operator(op.top()) <= level_operator(ex[i])&&op.top()!='#'&&op.top()!='('; op.pop())
            {
                cout << op.top();
            }
            op.push(ex[i]);
        }
    }
    //将栈中的剩余操作符输出
    while (op.top() != '#')
    {
        cout << op.top();
        op.pop();
    }
    cout << endl;
}

int main()
{

    string exp;
    cout << "请输入表达式" << endl;
    cin >> exp;
    Infix_convert(exp);
    

    return 0;
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容