递归算法实例应用(三)

简介: 递归算法实例应用(三):(POJ4132)四则运算表达式求值问题

递归算法实例应用(三)

四则运算表达式求值

Description

给你一个字符串表达式 str ,请你实现一个基本计算器来计算并返回它的值。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数 。

Input

一行,一个四则运算表达式。'*'表示乘法,'/'表示除法

Output

一行,该表达式的值,保留小数点后面两位

Sample Input

样例输入1:
34
样例输入2:
(2+3)*(5+7)+9/3

Sample Output

样例输出1:
34
样例输出2:
63

Tips

  • 1 <= s.length <= 3 * 105
  • str 由数字、'+''-''('')'组成
  • str 表示一个有效的表达式
  • '+'和'-'不能用作一元运算(例如, "+1" 和 "+(2 + 3)" 无效)
  • 输入中不存在两个连续的操作符
  • 每个数字和运行的计算将适合于一个有符号的32位整数




算法思想:

通过对题目的分析知道该题为递归形式定义的问题,其递归形式可描述如下:
请添加图片描述

所以,从递归定义出发,本题应分为三部分进行讨论,即表达式、项、因子,因为这三者相互嵌套组成了输入的一个表达式。

  1. 表达式,可以是一个单独的项,也可以由 项1 op 项2 组成。
  2. 项,可以是一个单独的因子,也可以由 因子1 op 因子2 组成。
  3. 因子,可以是一个单独的整数,也可以由 ( 表达式 ) 组成。

三者相互嵌套,递归表达构成了一个四则运算表达式。递归的终止条件为3中由整数形式定义的因子。

所以我们可以通过三个函数来实现对表达式、项、因子的求值。




代码逻辑:

  1. 一次性读取输入的表达式,
  2. 对于“表达式函数”而言有两种情况:

    • 该表达式为一个单独的项,此时仅需通过“项函数”读取改项的值,并作为结果返回即可
    • 若该表达式为 项1 op 项2,此时op应为‘+’或‘-’,先从输入缓冲区中消耗掉该op运算符,然后再读取下一个项的值,再做对应操作符计算即可。
    • 代码逻辑为:
    • int Expression_Value() {
          int result = Term_Value();      //取项1的值
          while (true) {
              char operation = peek();    //查看输入流中下一个字符
              if (operation == '+' || operation == '-') {
                  getchar();              //消耗掉输入流中下一个的'+'或'-'运算符
                  int nextTerm_Value = Term_Value();//若操作符为+或-,则应有项2,记录项2
                  if (operation == '+') {
                      result += nextTerm_Value;//更新结果为项1+项2
                  } else {
                      result -= nextTerm_Value;//更新结果为项1-项2
                  }
              } else {//若输入流中下一个字符不为+或-则表明该表达式为单项组成
                  break;
              }
          }
          return result;
      }
  3. 对于“项式函数”有两种情况:

    • 该项为一个单独的因子,此时仅需通过“因子函数”读取该因子的值,并作为结果返回即可
    • 若该项为 因子1 op 因子2,此时op应为‘*’或‘/’,先从输入缓冲区中消耗掉该op运算符,然后再读取下一个表达式的值,再做对应操作符计算即可。
    • 代码为:
    • int Term_Value() {
          int result = Factor_Value();//取因子1的值
          while (true) {
              char operation = peek();//查看输入流中下一个字符
              if (operation == '*' || operation == '/') {
                  getchar();//消耗掉这个'*'或'/'运算符
                  int nextFactor_Value = Factor_Value();//若操作符为*或/,则应有因子2,记录因子2
                  if (operation == '*') {
                      result *= nextFactor_Value;//更新结果为因子1*因子2
                  } else {
                      result /= nextFactor_Value;//更新结果为因子1/因子2
                  }
              } else {//若输入流中下一个字符不为*或/则表明该项为单因子组成
                  break;
              }
          }
          return result;
      }
  4. 对于“因子函数”同样也有两种情况:

    • 该因子为一个单独的整数因子,此时仅需将因子字符串转换成对应的整数类型,并作为结果返回即可。
    • 若该项为 ( 表达式 ),此时因子由表达式递归而成,而表达式被左右括号包裹着,所以我们应先从输入缓冲区中消耗掉左括号,然后调用“表达式函数”求该表达式的值,并将该表达式的值作为结果返回。
    • 其中关于字符串转整形数据,可按照秦九韶算法思想进行转换,比较简单,不再阐述,读者自行模拟一遍即可领会。
    • 代码为:
    • int Factor_Value() {
          int result = 0;//记录这个因子的结果
          char ch = peek();//查看输入流中下一个字符
          if (ch == '(') {//若下一个字符为(,则表明该因子为'(因子)'的形式
              getchar();//消耗掉'('
              result = Expression_Value();
              getchar();//消耗掉')'
          } else {//若下一个字符不为(,则表明该因子为整数形式,所以根据将字符转化为整形数字
              while (isdigit(ch)) {//如‘2’‘7’,result=(10*0+2)*10+7=2*10+7
                  result = 10 * result + (ch - '0');
                  getchar();//消耗掉该位字符。
                  ch = peek();
              }
          }
          return result;
      }
  5. 关于peek()函数的一点说明:

    • 该方法为编者自定义的一个函数,主要实现C++中int peek()函数功能。即返回在输入流中的下一个字符或如果是处于被入的文件的结尾处返回EOF。
    • peek()函数不会把字符从流中移除,也不改变字符所处位置。
    • 代码为:
    • int peek() {
          int ch = getchar();//读入一个字符
          ungetc(ch, stdin);//将该字符重新放入该字符在输入缓冲区中所处位置
          return ch;
      }




代码整合:

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

/* 表达式求值题目函数声明 */

int Expression_Value();     //求一个表达式的值
int Term_Value();           //求一个项的值
int Factor_Value();         //求一个因子的值

int main() {
    printf("%d\n", Expression_Value());//输出表达式的值。
    return 0;
}

int peek() {
    int ch = getchar();//读入一个字符
    ungetc(ch, stdin);//将该字符重新放入该字符在输入缓冲区中所处位置
    return ch;
}

//计算表达式的值
int Expression_Value() {
    int result = Term_Value();      //取项1的值
    while (true) {
        char operation = peek();    //查看输入流中下一个字符
        if (operation == '+' || operation == '-') {
            getchar();              //消耗掉输入流中下一个的'+'或'-'运算符
            int nextTerm_Value = Term_Value();//若操作符为+或-,则应有项2,记录项2
            if (operation == '+') {
                result += nextTerm_Value;//更新结果为项1+项2
            } else {
                result -= nextTerm_Value;//更新结果为项1-项2
            }
        } else {//若输入流中下一个字符不为+或-则表明该表达式为单项组成
            break;
        }
    }
    return result;
}

//计算项的值
int Term_Value() {
    int result = Factor_Value();//取因子1的值
    while (true) {
        char operation = peek();//查看输入流中下一个字符
        if (operation == '*' || operation == '/') {
            getchar();//消耗掉这个'*'或'/'运算符
            int nextFactor_Value = Factor_Value();//若操作符为*或/,则应有因子2,记录因子2
            if (operation == '*') {
                result *= nextFactor_Value;//更新结果为因子1*因子2
            } else {
                result /= nextFactor_Value;//更新结果为因子1/因子2
            }
        } else {//若输入流中下一个字符不为*或/则表明该项为单因子组成
            break;
        }
    }
    return result;
}

//计算因子的值
int Factor_Value() {
    int result = 0;//记录这个因子的结果
    char ch = peek();//查看输入流中下一个字符
    if (ch == '(') {//若下一个字符为(,则表明该因子为'(因子)'的形式
        getchar();//消耗掉'('
        result = Expression_Value();
        getchar();//消耗掉')'
    } else {//若下一个字符不为(,则表明该因子为整数形式,所以根据将字符转化为整形数字
        while (isdigit(ch)) {//如‘2’‘7’,result=(10*0+2)*10+7=2*10+7
            result = 10 * result + (ch - '0');
            getchar();//消耗掉该位字符。
            ch = peek();
        }
    }
    return result;
}


By Ss1Two 2023/01/16

目录
相关文章
|
3月前
|
存储 监控 JavaScript
基于布隆过滤器的 Node.js 算法在局域网电脑桌面监控设备快速校验中的应用研究
本文探讨了布隆过滤器在局域网电脑桌面监控中的应用,分析其高效空间利用率、快速查询性能及动态扩容优势,并设计了基于MAC地址的校验模型,提供Node.js实现代码,适用于设备准入控制与重复数据过滤场景。
188 0
|
2月前
|
运维 监控 JavaScript
基于 Node.js 图结构的局域网设备拓扑分析算法在局域网内监控软件中的应用研究
本文探讨图结构在局域网监控系统中的应用,通过Node.js实现设备拓扑建模、路径分析与故障定位,提升网络可视化、可追溯性与运维效率,结合模拟实验验证其高效性与准确性。
232 3
|
2月前
|
机器学习/深度学习 资源调度 算法
遗传算法模型深度解析与实战应用
摘要 遗传算法(GA)作为一种受生物进化启发的优化算法,在复杂问题求解中展现出独特优势。本文系统介绍了GA的核心理论、实现细节和应用经验。算法通过模拟自然选择机制,利用选择、交叉、变异三大操作在解空间中进行全局搜索。与梯度下降等传统方法相比,GA不依赖目标函数的连续性或可微性,特别适合处理离散优化、多目标优化等复杂问题。文中详细阐述了染色体编码、适应度函数设计、遗传操作实现等关键技术,并提供了Python代码实现示例。实践表明,GA的成功应用关键在于平衡探索与开发,通过精心调参维持种群多样性同时确保收敛效率
|
2月前
|
机器学习/深度学习 边缘计算 人工智能
粒子群算法模型深度解析与实战应用
蒋星熠Jaxonic是一位深耕智能优化算法领域多年的技术探索者,专注于粒子群优化(PSO)算法的研究与应用。他深入剖析了PSO的数学模型、核心公式及实现方法,并通过大量实践验证了其在神经网络优化、工程设计等复杂问题上的卓越性能。本文全面展示了PSO的理论基础、改进策略与前沿发展方向,为读者提供了一份详尽的技术指南。
粒子群算法模型深度解析与实战应用
|
2月前
|
机器学习/深度学习 算法 安全
小场景大市场:猫狗识别算法在宠物智能设备中的应用
将猫狗识别算法应用于宠物智能设备,是AIoT领域的重要垂直场景。本文从核心技术、应用场景、挑战与趋势四个方面,全面解析这一融合算法、硬件与用户体验的系统工程。
|
4月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习模型、算法与应用的全方位解析
深度学习,作为人工智能(AI)的一个重要分支,已经在多个领域产生了革命性的影响。从图像识别到自然语言处理,从语音识别到自动驾驶,深度学习无处不在。本篇博客将深入探讨深度学习的模型、算法及其在各个领域的应用。
917 3
|
4月前
|
机器学习/深度学习 人工智能 算法
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
AI-Compass 强化学习模块:理论到实战完整RL技术生态,涵盖10+主流框架、多智能体算法、游戏AI与金融量化应用
|
4月前
|
存储 监控 安全
企业上网监控系统中红黑树数据结构的 Python 算法实现与应用研究
企业上网监控系统需高效处理海量数据,传统数据结构存在性能瓶颈。红黑树通过自平衡机制,确保查找、插入、删除操作的时间复杂度稳定在 O(log n),适用于网络记录存储、设备信息维护及安全事件排序等场景。本文分析红黑树的理论基础、应用场景及 Python 实现,并探讨其在企业监控系统中的实践价值,提升系统性能与稳定性。
156 1
|
3月前
|
算法 数据可视化
matlab版本粒子群算法(PSO)在路径规划中的应用
matlab版本粒子群算法(PSO)在路径规划中的应用
|
4月前
|
存储 监控 算法
公司员工泄密防护体系中跳表数据结构及其 Go 语言算法的应用研究
在数字化办公中,企业面临员工泄密风险。本文探讨使用跳表(Skip List)数据结构优化泄密防护系统,提升敏感数据监测效率。跳表以其高效的动态数据处理能力,为企业信息安全管理提供了可靠技术支持。
122 0

热门文章

最新文章