表达式转换——中缀表达式转换成后缀表达式

要求:

输入在一行中给出不含空格的中缀表达式,可包含+、-、*、/以及左右括号

即二元运算符位于两个运算数中间

解决思路:

使用堆栈保存运算符

1.若遇到操作符,则直接输出

2.若是左括号,则将其压入堆栈中

3.若遇到的是右括号,表明括号内的中缀表达式已经扫描完毕,将栈顶的运算符出栈并输出,直到遇到左括号(左括号出栈,但不输出)

4. 若遇到的是运算符,若该运算符的优先级大于栈顶运算符的优先级,则把它压栈

若该运算符的优先级小于等于栈顶运算符的优先级,将栈顶运算符出栈并输出,再比较新的栈顶运算符,按照同样的处理方法,直到该运算符的优先级大于栈顶运算符的优先级为止,然后将该运算符压栈

5.若中缀表达式中的各对象处理完毕,则把堆栈中存留的运算符一并输出

代码:

//中缀表达式转换成后缀表达式


#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
#include<ctype.h>

#define MAXL 21

/*------堆栈定义-------*/
 
typedef char ElementType;
typedef int Position;
typedef struct SNode *PtrToSNode;
struct SNode{
    ElementType *Data;
    Position Top;
    int MaxSize;
};
typedef PtrToSNode Stack;

Stack CreateStack(int MaxSize);
bool IsEmpty(Stack S);
void Push(Stack S,ElementType X);
ElementType Peek(Stack S);//访问栈顶元素,但不出栈 
ElementType Pop(Stack S);

/*------堆栈定义结束-------*/

//运算符的优先级类型 
typedef enum{
    //左括号,右括号,加,减,乘,除 ,结束符, 数字 
    lpr,rpr,plus,minus,times,divide,eos,operand
}Precedence;

bool IsSign(char *expr,int i);//判断'+''-'是运算符还是数字前的加减号 
char GetOp(char *expr,int *i,char *Postfix,int *j);//获取运算符 
Precedence GetToken(char op);//获取运算符 
void ToPostfix(char *expr);//后缀表达式核心函数 


int main()
{
    char Str[MAXL];
    printf("请输入中缀表达式:");
    scanf("%s",Str);
    printf("输出的后缀表达式为:");
    ToPostfix(Str);
    return 0;
 } 



/*------表达式转换核心函数-------*/
void ToPostfix(char *expr)
{
    int i,j,L;
    char Postfix[2*MAXL],Op;
    Stack S;
    Precedence token;
    S=CreateStack(MAXL);
    L=strlen(expr);
    j=0;//j指向 Postfix[]中当前要写入的位置
    for(i=0;i<L;i++){
        Op=GetOp(expr,&i,Postfix,&j); 
        token=GetToken(Op);
        if(token==operand)continue;//数字不处理
         switch(token){//处理运算符 
             case lpr:Push(S,'(');break;//左括号入栈 
             case rpr://右括号
             /*括号内的中缀表达式扫描完毕,把左括号前的所有运算符写入Postfix[]*/ 
                 while(Peek(S)!='('){//访问栈顶元素 
                     Postfix[j++]=Pop(S);//出栈 
                     Postfix[j++]=' '; //写入空格 
                 }
                 Pop(S);//删除左括号
                 break;
            default://其他运算符
                //当前运算符优先级小于等于栈顶运算符优先级,直接出栈并输出 
                while(!IsEmpty(S) && Peek(S)!='(' && token<=GetToken(Peek(S))){
                    Postfix[j++]=Pop(S);
                    Postfix[j++]=' ';
                }
                Push(S,Op);//当前运算符优先级大于栈顶运算符优先级 ,压栈 
                break;
         }
    } 
    //中缀表达式中的各对象处理完毕,把堆栈中存留的运算符一并输出
    while(!IsEmpty(S)){
        Postfix[j++]=Pop(S);
        Postfix[j++]=' ';
    }
    Postfix[j-1]='\0';
    printf("%s\n",Postfix);
        
}
/*------表达式转换核心函数结束-------*/


/*------堆栈操作-------*/
Stack CreateStack(int MaxSize)
{
    Stack S=(Stack)malloc(sizeof(struct SNode));
    S->Data =(ElementType *)malloc(sizeof(ElementType)*MaxSize);
    S->MaxSize =MaxSize;
    S->Top =-1;
    return S;
}
bool IsEmpty(Stack S)
{
    return (S->Top ==-1);
}
void Push(Stack S,ElementType X)
{
    //简版入栈,不考虑栈满
    S->Data [++(S->Top) ]=X; //注意先加Top 
}
ElementType Peek(Stack S)
{
    return (S->Data [S->Top ]); 
}
ElementType Pop(Stack S)
{
    //简版出栈,不考虑栈空 
    return (S->Data [(S->Top )--]);
}

/*------堆栈操作结束-------*/

/*------辅助函数-------*/

bool IsSign(char *expr,int i)
{
    //如果前一个字符不是数字且不是右括号,那么这个字符是正负号 
    //如果它是表达式的第一个字符,也是正负号 
    if(!i || (!isdigit(expr[i-1]) && (expr[i-1]!=')'))) //是正负号 
        return true;
    else return false;//是运算符 
}
char GetOp(char *expr,int *i,char *Postfix,int *j)
{
    //如果是数字则直接写入Postfix[]并返回‘0’
    //如果是运算符则返回字符
    
    if(isdigit(expr[(*i)])){
        //读入一个纯数字
        while(isdigit(expr[(*i)]) || (expr[(*i)]=='.'))
            Postfix[(*j)++]=expr[(*i)++];
        Postfix[(*j)++]=' '; 
        (*i)--;
        return '0';
    } 
    //不是纯数字——运算符或正负号,括号 
     switch(expr[(*i)]){
         case'+':
             if(IsSign(expr,(*i))){//正号 
                 (*i)++;
                 return GetOp(expr,i,Postfix,j);//继续扫描 
             }
             else return '+';//运算符 
        case'-':
            if(IsSign(expr,(*i))){//负号 
                Postfix[(*j)++]='-';//放入后缀表达式 
                (*i)++;
                return GetOp(expr,i,Postfix,j);//继续扫描 
            }
            else return '-';//运算符 
        default:
            return expr[(*i)];//括号,乘除 
     }
}
Precedence GetToken(char op)
{
    //返回运算符优先级类型
    switch(op){
        case '(':return lpr;
        case ')':return rpr;
        case '+':return plus;
        case '-':return minus;
        case '*':return times;
        case '/':return divide;
        case '\0':return eos;
        default:return operand;//数字 
    } 
}

/*------辅助函数结束-------*/

运行:

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值