数据结构与算法之中缀表达式转换为后缀表达式

一、中缀表达式转换为后缀表达式

      1.中缀表达式和后缀表达式

  • 中缀表达式是符合人类正常逻辑思维的;
  • 后缀表达式则是比较契合计算机的运算。

      2.中缀表达式转换为后缀表达式

      思考:我们要如何将(1-2)*(4+5)转换为1 2 - 4 5 + *呢?

      提示:利用栈的“记忆”,符号都推入栈即可!

      案例:1+ (2-3) * 4 + 10/5

      (1)首先遇到第一个输入是数字1,数字在后缀表达式中都是直接输出,接着是符号"+",入栈:

      (2)第三个字符是"(",依然是符号,入栈,接着是数字2,输出,然后是符号"-",入栈:

      (3)接下来是数字3,输出,紧跟着是")",此时,我们需要去匹配栈里的"(",然后再匹配前将栈顶数据依次出栈(这就好比括号里优先执行的道理),将"("和"-"出栈,并输出"-":

      (4)紧接着是符号"*",直接入栈:

      (5)遇到数字4,输出,之后是符号"+",此时栈顶元素是符号"*",此时按照先乘除后加减的原理,此时栈顶的乘号优先级比即将入栈的加号要大,所以,先让栈内"*"出栈,再让"+"出栈,并依次输出,两个全出栈就为空栈了,再让4后面的"+"入栈:

      (6)紧接着数字10,输出,最后是符号"/",进栈:

      (7)最后一个数字5,输出,所有的输入处理完毕,但是栈中仍有数据,所以将栈中的符号依次出栈打印即可。

      规则总结:从左到右遍历中缀表达式的每个数字和符号,若是数字则直接输出,若是符号,则判断其与栈顶符号的优先级,是右括号或是优先级低于栈顶符号,则栈顶元素依次出栈并输出,直到遇到左括号或栈空才将后一个符号入栈。

      3.代码实现

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define STACK_INIT_SIZE 20
#define STACKINCREMENT 10

typedef char ElemType;
typedef struct{
    ElemType *base;
    ElemType *top;
    int stackSize;
}sqStack;

// 创建一个栈
void InitStack(sqlStack *s){
    s->base = (ElemType *)malloc(STACK_INIT_SIZE *sizeof(ElemType));

    if(!s->base){
        exit(0);
    }
    
    s->top = s->base;
    s->stackSize = STACK_INIT_SIZE;
}

// 压栈
void Push(sqStack *s, ElemType e){

    if(s->top - s->base >= s->stackSize){
        s->base = (ElemType *)realloc(s->base, (s->stackSize + STACKINCREMENT)*sizeof(ElemType));
        if(!s->base){
            exit(0);
        }
    }

    *(s->top) = e;
    s->top++;
}

void Pop(sqStack *s, ElemType *e){
    if(s->top == s->base){
        return;
    }
    *e = *--(s->top);
}

// 计算栈的当前容量 
int StackLen(sqStack s){
    return (s.top - s.base);
}

// 中缀表达式转换为后缀表达式
int main(){
    sqStack s;
    char c, e;
    
    InitStack(&s);

    printf("请输入中缀表达式,以#号作为结束标志:");
    scanf("%c", &c);

    while(c!='#'){
        while(c>='0' && c<='9'){ // 循环输入解决多位数的输出问题,如果是数字直接打印
            printf("%c", c);
            scanf("%c", &c);
            if(c<'0' || c>'9'){
                printf(" ");
            }
        }
        if(')' == c){ // 如果是右括号,就出栈,直到弹出第一个左括号为止
            Pop(&s, &e);
            while('(' != e){
                printf("%c", e);
                Pop(&s, &e)
            }
        }else if('+' == c || '-' == c){
            if(!StackeLen(s)){ // 如果栈为空,直接入栈
                Push(&s, c);
            }else{ //如果栈不为空,先弹栈,比较优先级
                do{
                       Pop(&s, &e);
                       if('(' == e){ // 如果弹栈的元素是左括号,则把左括号再入栈
                           Push(&s, e);
                       }else{ // 不是左括号,只能是+ - * / ,那么就把之前入栈的符号先打印出来
                           printf("%c ", e);
                       }
                  }while(StackLen(s) && '(' != e);
                  Push(&s, c); // 最后将新输入的+ -入栈
            }
        }else if('*' == c || '/' == c || '(' == c){
            Push(&s, c)
        }else if('#' == c){
            break;  
        }else{
            printf("\n出错:输入格式错误!\n")
        }
        scanf("%c", &c);
    }

    while(StackLen(s)){
        Pop(&s, &e);
        printf("&c ", e);
    }
    
    return 0;
}

 

本文为原创文章,如果对你有一点点的帮助,别忘了点赞哦!比心!如需转载,请注明出处,谢谢!

 

转载于:https://my.oschina.net/aibinxiao/blog/1837133

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值