表达式求值设计实验报告

课程设计题目:表达式求值

一、问题描述与基本要求

利用栈,实现以下功能:

  1. 中缀表达式求值;
  2. 中缀表达式转后缀表达式;
  3. 后缀表达式求值。

假设用户输入的表达式均合法,且运算符只含+(加号)、-(减号)、*/%(),允许浮点数(浮点数计算取模规定为向零取整后得到整数再计算取模)。

二、概要设计

1. 数据结构的设计

我们利用栈来实现上述3个功能。具体原因见后文算法的设计

2. 算法的设计

2.1 表达式读入与预处理

用户从键盘输入一个语法正确的中缀/后缀表达式,但格式可能并不标准,例如有多余的空格。另外,为了在后面计算表达式编码更方便,我想利用C++中的istringstream,所以要将表达式存储在字符串中,且数与数、数与符号、符号与符号之间都有空格,最后在字符串末尾加上#(原因见下)。

用length表示输入的中缀表达式字符串长度,则

时间复杂度 空间复杂度
O ( l e n g t h ) O(length) O(length) O ( l e n g t h ) O(length) O(length)
2.2 计算中缀表达式

先定义运算符的优先级。注意运算符在栈内和栈外的优先级是不同的,这是为了实现同优先级能从左往右计算。

运算符 + - * / % ( ) # ;
isp(栈内优先级) 3 5 1 6 0
icp(栈外优先级) 2 4 6 1 0

定义#;,是为了后面统一处理表达式求值。

接下来,我们定义两个栈:数值栈(num_stack)和符号栈(sgn_stack)。

从左往右扫描中缀表达式,如果:

  1. 遇到数值就直接将它压入数值栈;
  2. 遇到运算符(记当前运算符为cur),检查符号栈的栈顶运算符的优先级
    1. 栈顶优先级小于cur,则直接压入cur
    2. 栈顶优先级大于cur,则弹出栈顶运算符和数值栈的两个数来计算,再把计算结果压入数值栈。重复直到栈顶运算符的优先级不再大于cur,再将cur压入。
    3. 栈顶优先级等于cur,从上面的运算符优先级的表格中我们可以知道这时候栈顶是左括号,cur是右括号,那么直接将这两个括号扔掉就好了。
  3. 最后数值栈里就只剩下一个数,就是整个中缀表达式的计算结果

如果我们不在原本的中缀表达式后面加#;,那么还需要把符号栈中的运算符依次弹出来并计算,这无疑让编码更加繁琐更易出错。所以,不如在后面加上#;,并把优先级设计成最低(0),统一处理。

伪代码如下

for (从左到右扫描中缀表达式)
    if (cur == 数值)
        num_stack.push(cur)
    else // cur == 运算符
        while (isp(sgn_stack.top()) > icp(cur))
            b = num_stack.top(), num_stack.pop()
            a = num_stack.top(), num_stack.pop()
            用 sgn_stack.top() 计算 a 和 b,结果存到 c
            num_stack.push(c)
        sgn_stack.push(cur)

用n表示输入的中缀表达式中运算符个数,则

时间复杂度 空间复杂度
O ( n ) O(n) O(n) O ( n ) O(n) O(n)
2.3 中缀表达式转后缀表达式

我们只需要一个符号栈(sgn_stack)就够了。

从左往右扫描中缀表达式,如果:

  1. 遇到数值就直接将它输出;
  2. 遇到运算符(记当前运算符为cur),检查符号栈的栈顶运算符的优先级
    1. 栈顶优先级小于cur,则直接压入cur
    2. 栈顶优先级大于cur,则弹出栈顶运算符并输出。重复直到栈顶运算符的优先级不再大于cur,再将cur压入。
    3. 栈顶优先级等于cur,从上面的运算符优先级的表格中我们可以知道这时候栈顶是左括号,cur是右括号,那么直接将这两个括号扔掉就好了,因为后缀表达式不需要括号。

同样,这里在原来的中缀表达式后加上#;会更方便。

后缀表达式并不需要在最后面也加上#;(因为它的计算和编码已经够简单了)。当然,加上也没问题。

伪代码如下

for (从左到右扫描中缀表达式)
    if (cur == 数值)
        输出 cur
    else // cur == 运算符
        while (isp(sgn_stack.top()) > icp(cur))
            输出 sgn_stack.top() sgn_stack.pop()
        sgn_stack.push(cur)

用length表示输入的中缀表达式字符串长度,则

时间复杂度 空间复杂度
O ( l e n g t h ) O(length) O(length) O ( l e n g t h ) O(length) O(length)
2.4 计算后缀表达式

后缀表达式的计算就简单了:遇数压栈,遇符就弹两个数来算。

for (从左到右扫描后缀表达式)
    if (cur == 数值)
        num_stack
  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值