2.4.3、求表达式的值

本文介绍了后缀表达式(逆波兰表达式),它将运算符置于运算项之后,可借助栈结构求值。还阐述了迪杰斯特拉的调度场算法,用于将普通表达式转换为后缀表达式,该算法借助空栈和空数组,按规则遍历字符完成转换,最后给出了完整解决方案及可编译运行的源码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 表达式就是由变量、常量以及运算符组合而成的式子。
  • 如何用栈结构求一个表达式的值?

1、后缀表达式

  • 1929 年,波兰逻辑学家 J・卢卡西维兹提出了一种全新的表示表达式的方法,称为后缀表达式或逆波兰表达式。和普通表达式不同,后缀表达式习惯将运算符写在它的运算项之后,且整个表达式中不用括号()表明运算的优先级关系。
    • 3!为例,! 为运算符,3 为运算项,因此3!本身就是一个后缀表达式
    • 再以 4*2 为例,* 为运算符,4 和 2 作为它的运算项,其后缀表达式为4 2 *
  • 3!+4*2/(1-5)^2转换成后缀表达式(将表达式中所有运算符放置在它的运算项之后):
    • ! 运算符对应的运算项为 3,转换后得到3 !
    • + 运算符对应的运算项是3!4*2/(1-5)^2,转换之后得到:3! 4*2/(1-5)^2 +
    • * 运算符对应的运算项是 4 和 2,转换之后得到4 2 *
    • / 运算符对应的运算项是 4 2 *(1-5)^2,转换后得到4 2 * (1-5)^2 /
    • - 运算符对应的运算项是 1 和 5,转换后得到1 5 -
    • ^ 运算符对应的运算项是1 5 -和 2 ,转换后得到1 5 - 2 ^
    • 整合之后,整个普通表达式就转换成了3 ! 4 2 * 1 5 - 2 ^ / +,这就是其对应的后缀表达式
  • 后缀表达式完全舍弃了表达式本该有的可读性,相比普通表达式,后缀表达式的值可以借助栈存储结构求得。具体求值的过程:当用户给定一个后缀表达式时,按照从左到右的顺序依次扫描表达式中的各个运算项和运算符,对它们进行如下处理:
    • 遇到运算项时,直接入栈
    • 遇到运算符时,将位于栈顶的运算项出栈:
      • 对于 ! 运算符,取栈顶 1 个运算项
      • 其它运算符则取栈顶 2 个运算项,第一个取出的运算项作为该运算符的右运算项,另一个作为左运算项
    • 求此表达式的值并将其入栈
  • 重复以上操作,直到栈中仅存在一个运算项为止,此运算项即为整个表达式的值。
  • 3 ! 4 2 * 1 5 - 2 ^ / +表达式为例,求值的过程为:
    • 从 3 开始,它是运算项,因此直接入栈:

    • ! 作为运算符,从栈顶取一个运算项 3,求 3! 的值(3! = 3*2*1=6)并将其入栈:

    • 将 4 和 2 先后入栈:

    • 对于 * 运算符,取栈顶两个运算项( 2 和 4),先取出的 2 作为 * 的右操作数,4 作为左操作数。求的 4 * 2 的值 8 ,并将其入栈:

    • 将 1 和 5 先后入栈:

    • 对于 - 运算符,取栈顶两个运算项(5 和 1),计算出 1-5 的值为 -4,将其入栈:

    • 将 2 入栈:

    • 对于 ^ 运算符,取栈顶两个运算项(2 和 -4),计算出 -4^2 的值 16 ,将其入栈:

    • 对于 / 运算符,取栈顶两个运算项(16 和 8),计算出 8/16 的值 0.5,将其入栈:

    • 对于 + 运算符,取栈顶两个运算符(0.5 和 6),计算出 6+0.5 的值 6.5,将其入栈:

  • 由此,整个求值的过程就结束了,最终表达式的值为 6.5。
  • 代码实现:
// 根据给定的后缀表达式 postexp,计算它的值
typedef struct
{
    double data[MAXSIZE];
    int top;
}Stack_num;

void InitStack_num(Stack_num **s)
{
    *s = (Stack_num *)malloc(sizeof(Stack_num));
    (*s)->top = -1;
}

bool Push_num(Stack_num **s, double e)
{
    if ((*s)->top == MAXSIZE - 1)
        return false;
    (*s)->top++;
    (*s)->data[(*s)->top] = e;
    return true;
}

bool Pop_num(Stack_num **s, double *e)
{
    if ((*s)->top == -1)
        return false;
    *e = (*s)->data[(*s)->top];
    (*s)->top--;
    return true;
}

// 计算后缀表达式的值
double compvalue(char *postexp)
{
    Stack_num *num;
    int i = 1;
    double result;
    double a, b;
    double c
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

融码一生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值