C语言实现中缀表达式转换前缀表达式和后缀表达式

4

基本思想

人们习惯的运算方式是中缀表达式,而碰到前缀,后缀方式就变迷茫。其实仅仅是一种表达式的方式而已(不被你习惯的方式),我这里教你一种也许你老师都没跟你讲的简单转换方式。

一个中缀式到其他式子的转换方法:

这里我给出一个中缀表达式a+b*c-(d+e)

第一步:按照运算符的优先级对所有的运算单位加括号,式子变成:((a+(b*c))-(d+e))

第二步:转换前缀与后缀表达式

前缀:把运算符号移动到对应的括号前面

则变成:-( +(a *(bc)) +(de)),把括号去掉:-+a*bc+de 前缀式子出现

后缀:把运算符号移动到对应的括号后面

则变成拉:((a(bc)* )+ (de)+ )-,把括号去掉:abc*+de+- 后缀式子出现

发现没有,前缀式,后缀式是不需要用括号来进行优先级的确定的。

转自:https://zhuanlan.zhihu.com/p/47372892

程序实现原理:

  • 中缀转换前缀:

    (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
    (2) 从右至左扫描中缀表达式;
    (3) 遇到操作数时,将其压入S2;
    (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
    (4-1) 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
    (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
    (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
    (5) 遇到括号时:
    (5-1) 如果是右括号“)”,则直接压入S1;
    (5-2) 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃;
    (6) 重复步骤(2)至(5),直到表达式的最左边;
    (7) 将S1中剩余的运算符依次弹出并压入S2;
    (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。

  • 中缀转换后缀:

    (1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
    (2) 从左至右扫描中缀表达式;
    (3) 遇到操作数时,将其压入S2;
    (4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
    (4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
    (4-2) 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
    (4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
    (5) 遇到括号时:
    (5-1) 如果是左括号“(”,则直接压入S1;
    (5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
    (6) 重复步骤(2)至(5),直到表达式的最左边;
    (7) 将S1中剩余的运算符依次弹出并压入S2;
    (8) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。

C语言实现

#include <stdio.h>
#include <string.h>
#define ElemType char
#define MaxSize 50

typedef struct
{
    ElemType data[MaxSize];
    int top;
} SqStack;

void initStack(SqStack &S)
{
    S.top = -1; //初始化栈顶指针
}

bool StackEmpty(SqStack S)
{
    if (S.top == -1) //栈空
        return true;
    else
        return false; //栈不空
}

bool Push(SqStack &S, ElemType x)
{
    if (S.top == MaxSize - 1) //栈满 不能执行入栈操作
        return false;
    S.top++; //指针先加1,再入栈
    S.data[S.top] = x;
    return true;
}

bool Pop(SqStack &S, ElemType &x)
{
    if (S.top == -1) //栈空 不能执行出栈操作
        return false;
    x = S.data[S.top]; //先出栈 指针再减1
    S.top--;
    return true;
}

bool GetPop(SqStack S, ElemType &x)
{
    if (S.top == -1) //栈空报错
        return false;
    x = S.data[S.top]; //用x存储栈顶元素
    return true;
}
// 转换为前缀表达式
void PolishNotation(SqStack S, char NifixExpression[])
{
    char PostfixExpression[60]; //在字符数组最后添加'\0',作为结束标志
    int index = 0;
    // 从右至左运算
    char *p = &NifixExpression[strlen(NifixExpression) - 1];
    // printf("长度为:%c\n", *(p));
    for (int i = strlen(NifixExpression) - 1; i >= 0; i--)
    {
        // printf("值为:%c\n", *(p--));
        if (*p == ')') //如果为右括号,直接入栈
        {
            Push(S, *p);
            p--;
        }
        else if (*p == '(') //若为左括号,依次弹出栈中运算符,直到')',并删除')'--用出栈不保存数据实现
        {
            while (S.data[S.top] != ')')
            {
                char temp;
                Pop(S, temp);
                if (temp == '+' || temp == '-' || temp == '*' || temp == '/')
                {
                    PostfixExpression[index] = temp;
                    index++;
                }
            }
            char temp;
            Pop(S, temp); //把右括号也出栈
            p--;
        }
        else if (*p >= 'A' && *p <= 'Z') //这里用大写字母代替表达式中的数字,为大写字母则直接进入前缀表达式
        {
            PostfixExpression[index] = *p;
            index++;
            p--;
        }
        else
        {
            if (*p == '+' || *p == '-')
            {
                if (S.data[S.top] == ')' || StackEmpty(S)) //如果遍历到'+''-',且栈为空或栈顶为')',直接入栈
                {
                    Push(S, *p);
                    p--;
                }
                else
                {
                    while (S.data[S.top] != ')' && !StackEmpty(S)) //依次弹出较高优先级运算符,直到')'
                    {
                        char temp;
                        Pop(S, temp);
                        PostfixExpression[index] = temp;
                        index++;
                    }
                }
            }
            else
            {
                Push(S, *p);
                p--;
            }
        }
    }
    if (!StackEmpty(S)) //若栈不为空,依次弹出其中的运算符
    {
        while (S.top != -1)
        {
            char temp;
            Pop(S, temp);
            PostfixExpression[index] = temp;
            index++;
        }
    }
    PostfixExpression[index] = '\0'; //在字符数组后加'\0',作为结束标志

    printf("前缀表达式为:");
    for (int i = strlen(NifixExpression) - 1; i >= 0; i--)
    {
        printf("%c", PostfixExpression[i]);
    }
    printf("\n");
}
// 转换为后缀表达式
void RPN(SqStack S, char NifixExpression[])
{
    char PostfixExpression[60]; //在字符数组最后添加'\0',作为结束标志
    int index = 0;
    char *p = NifixExpression;
    while (*p != '\0')
    {
        if (*p == '(') //如果为左括号,直接入栈
        {
            Push(S, *p);
            p++;
        }
        else if (*p == ')') //若为右括号,依次弹出栈中运算符,直到'(',并删除'('--用出栈不保存数据实现
        {
            while (S.data[S.top] != '(')
            {
                char temp;
                Pop(S, temp);
                if (temp == '+' || temp == '-' || temp == '*' || temp == '/')
                {
                    PostfixExpression[index] = temp;
                    index++;
                }
            }
            char temp;
            Pop(S, temp); //把左括号也出栈
            p++;
        }
        else if (*p >= 'A' && *p <= 'Z') //这里用大写字母代替表达式中的数字,为大写字母则直接进入后缀表达式
        {
            PostfixExpression[index] = *p;
            index++;
            p++;
        }
        else
        {
            if (*p == '+' || *p == '-')
            {
                if (S.data[S.top] == '(' || StackEmpty(S)) //如果遍历到'+''-',且栈为空或栈顶为'(',直接入栈
                {
                    Push(S, *p);
                    p++;
                }
                else
                {
                    while (S.data[S.top] != '(' && !StackEmpty(S)) //依次弹出较高优先级运算符,直到'('
                    {
                        char temp;
                        Pop(S, temp);
                        PostfixExpression[index] = temp;
                        index++;
                    }
                }
            }
            else
            {
                Push(S, *p);
                p++;
            }
        }
    }
    if (!StackEmpty(S)) //若栈不为空,依次弹出其中的运算符
    {
        while (S.top != -1)
        {
            char temp;
            Pop(S, temp);
            PostfixExpression[index] = temp;
            index++;
        }
    }
    PostfixExpression[index] = '\0'; //在字符数组后加'\0',作为结束标志

    printf("后缀表达式为:%s", PostfixExpression);
}
int main()
{
    SqStack S;
    initStack(S);

    char NifixExpression[] = {'(', '(', 'A', '+', 'B', ')', '*', 'C', ')', '-', '(', 'E', '-', 'F', ')', '\0'};
    // char NifixExpression[] = {'A', '*', '(', 'B', '+', 'C', ')', '-', 'D', '\0'};
    printf("中缀表达式为:%s", NifixExpression);
    printf("\n");
    PolishNotation(S, NifixExpression);
    RPN(S, NifixExpression);
}

运行结果:

结果

参考:https://zhuanlan.zhihu.com/p/135433833