栈的应用案例2:中缀表达式转后缀表达式

栈的应用:中缀表达式转后缀表达式

计算机的本质工作就是做数学运算,那计算机可以读入字符串
“9 + (3 - 1) * 5 + 8 / 2”并计算值吗?
后缀表达式  ==?符合计算机运算
波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式对应的,
我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯

实例:
5 + 4=> 5 4 +  
1 + 2 * 3 => 1 2 3 * +  
8 + ( 3 – 1 ) * 5 => 8 3 1 – 5 * +  
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的“运算习惯”
如何将中缀表达式转换成后缀表达式?
中缀转后缀算法:
遍历中缀表达式中的数字和符号
   1.对于数字:直接输出
   2.对于符号:
               左括号:入栈(左括号优先级最低)
           运算符:与栈顶符号进行优先级比较
               若栈顶符号优先级低:入栈    
                       若栈顶符号优先级不低:将栈顶符号弹并输出,之后进入栈
           右括号:将栈顶符号弹出并输出,直到匹配左括号
   3.遍历结束:将栈中所有符号弹出并输出

计算机是如何基于后缀表达式计算的?
8 3 1 – 5 * +
遍历后缀表达式中的数字和符号
    1.对于数字:进栈
    2.对于符号:
                从栈中弹出右操作数
                从栈中弹出左操作数
    3.根据符号进行运算
    4.将运算结果压入栈中

    5.遍历结束:栈中的唯一数字为计算结果    

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include<stdio.h>
#include <string.h>
#include "linkstack.h"
#include "linklist.h"

int i=0;//全局变量记录次数
//判断是否为操作符
int isOper(char c)
{
    int ret = 0;
    if ((c== '+')||(c== '-')||(c== '*')||(c== '/'))
    {
        ret = 1;
        return ret ;
    }    
    return 0;
}
//判断是否为数
int isNum(char c)
{
    return ('0'<=c)&&(c<='9');
}
//计算
int express(int left,int right,char op)
{
    int ret = 0;
    switch(op)
    {
    case '+':
        ret = left + right;
        break;
    case '-':
        ret = left - right;
        break;
    case '*':
        ret = left * right;
        break;
    case '/':
        ret = left / right;
    default:
        break;
    }
    return ret ;
}
//判断操作符的优先级
int priority(char c)
{
    int ret = 0;
    if ((c=='+')||(c=='-'))
    {
        ret = 1;
    }
    if ((c=='*')||(c=='/'))
    {
        ret = 2;
    }
    return ret;
}

//通过二级指针改变一级指针的值
//保存转换后的 后缀表达式字符串
void output(char c,char **p)
{
    if (c!='\0')
    {
        printf("%c",c);
        (*p)[i++]=c;
    }
    (*p)[i] = '\0';
}
//判断(
int isLeft(char c)
{
    int ret =0;
    if (c=='(')
    {
        ret = 1;
        return ret;
    }
    return ret;
}
//判断)
int isRight(char c)
{
    int ret =0;
    if (c==')')
    {
        ret = 1;
        return ret;
    }
    return ret;
}
//将字符转为对应的int数字
int value(char c)
{
    return (c-'0');
}
//扫描 中缀转后缀算法
/************************************************************************/
/* 1.对于数字:直接输出
   2.对于符号:
           左括号:入栈(左括号优先级最低) 
            运算符:与栈顶符号进行优先级比较
                    若栈顶符号优先级低:入栈    
               若栈顶符号优先级不低:将栈顶符号弹并输出,之后进入栈
            右括号:将栈顶符号弹出并输出,直到匹配左括号
   3.遍历结束:将栈中所有符号弹出并输出

   char **p;通过二级指针做函数参数 改变一级指针的值
/************************************************************************/
void scanner(const char *code,char **p)
{
    int i = 0,ret = 0;
    LinkStack*stack = NULL;
    stack = LinkStack_Create();
    if (stack ==NULL)
    {
        ret = -1;
        printf("stack == null %d\n",ret);
        return;
    }
    //扫描字符串
    while (code[i]!='\0')
    {
        if (isNum(code[i]))
        {
            output(code[i],p);
        }
        else if(isOper(code[i]))
        {
            while (priority(code[i])<=priority((char)(int)LinkStack_Top(stack)))
            {
                output((char)(int)LinkStack_Pop(stack),p);
            }
            LinkStack_Push(stack,(void*)(int)code[i]);
        }
        else if(isLeft(code[i]))
        {
            LinkStack_Push(stack,(void*)(int)code[i]);
        }
        else if(isRight(code[i]))
        {
            while (!isLeft((char)(int)LinkStack_Top(stack)))
            {
                output((char)(int)LinkStack_Pop(stack),p);
            }
            //弹出左括号
            LinkStack_Pop(stack);
        }
        else
        {
            printf("Invalid code\n");
            break;
        }
        i++;
    }
    //遍历结束 将栈中所有符号弹出
    while((LinkStack_Size(stack)>0)&&(code[i]=='\0'))
    {
        output((char)(int)LinkStack_Pop(stack),p);
    }
    LinkStack_Destroy(stack);
}
/************************************************************************/
//计算机 根据后缀表达式进行计算 返回计算结果
/* 计算机是如何基于后缀表达式计算的?
遍历后缀表达式中的数字和符号
    1.对于数字:进栈
    2.对于符号:
                从栈中弹出右操作数
                从栈中弹出左操作数
    3.根据符号进行运算
    4.将运算结果压入栈中
    5.遍历结束:栈中的唯一数字为计算结果      */                                
/************************************************************************/

int compute(const char *exp)
{
    int i = 0,ret = -1;
    LinkStack*stack = NULL;
    stack = LinkStack_Create();
    if (stack ==NULL)
    {
        ret = -1;
        printf("stack == null %d\n",ret);
        return ret;
    }
    //扫描后缀表达式
    while (exp[i]!='\0')
    {
        if (isNum(exp[i]))
        {
            LinkStack_Push(stack,(void*)value(exp[i]));
        }
        else if (isOper(exp[i]))
        {
            int right = (int)LinkStack_Pop(stack);
            int left = (int)LinkStack_Pop(stack);
            int num = express(left,right,exp[i]);
            printf("num:%d\n",num);
            LinkStack_Push(stack,(void*)num);
        }
        else
        {
            printf("invalid express\n");
            break;
        }
        //printf("i:%d\n",i);
        i++;
        
    }
    //遍历结束 将栈中所有符号弹出
    while((LinkStack_Size(stack)>0)&&(exp[i]=='\0'))
    {
        ret = (int)LinkStack_Pop(stack);
    }
    LinkStack_Destroy(stack);
    return ret;
} 
int main()
{
    char *a;
    int num ;
    //目前只支持个位数字 10+ 出错
    const char *code = "8+(3-1)*5";
    a = (char*)malloc(100*sizeof(a));
    //指针做输入 主调函数分配内存
    scanner(code,&a);
    printf("\n%s\n",a);
    num = compute(a);
    printf("num:%d\n",num);

    free(a);
    system("pause");
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值