递归算法实例应用(三)

简介: 递归算法实例应用(三):(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

目录
相关文章
|
7天前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
38 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
3月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
61 3
|
3月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的优化算法及其应用
【10月更文挑战第8天】 本文将探讨深度学习中常用的优化算法,包括梯度下降法、Adam和RMSProp等,介绍这些算法的基本原理与应用场景。通过实例分析,帮助读者更好地理解和应用这些优化算法,提高深度学习模型的训练效率与性能。
242 63
|
7天前
|
存储 缓存 算法
探索企业文件管理软件:Python中的哈希表算法应用
企业文件管理软件依赖哈希表实现高效的数据管理和安全保障。哈希表通过键值映射,提供平均O(1)时间复杂度的快速访问,适用于海量文件处理。在Python中,字典类型基于哈希表实现,可用于管理文件元数据、缓存机制、版本控制及快速搜索等功能,极大提升工作效率和数据安全性。
39 0
|
2月前
|
机器学习/深度学习 人工智能 算法
探索人工智能中的强化学习:原理、算法与应用
探索人工智能中的强化学习:原理、算法与应用
|
2月前
|
机器学习/深度学习 算法 数据挖掘
C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出
本文探讨了C语言在机器学习中的应用及其重要性。C语言以其高效性、灵活性和可移植性,适合开发高性能的机器学习算法,尤其在底层算法实现、嵌入式系统和高性能计算中表现突出。文章还介绍了C语言在知名机器学习库中的作用,以及与Python等语言结合使用的案例,展望了其未来发展的挑战与机遇。
50 1
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
63 1
|
2月前
|
缓存 算法 网络协议
OSPF的路由计算算法:原理与应用
OSPF的路由计算算法:原理与应用
53 4
|
2月前
|
机器学习/深度学习 监控 算法
基于反光衣和检测算法的应用探索
本文探讨了利用机器学习和计算机视觉技术进行反光衣检测的方法,涵盖图像预处理、目标检测与分类、特征提取等关键技术。通过YOLOv5等模型的训练与优化,展示了实现高效反光衣识别的完整流程,旨在提升智能检测系统的性能,应用于交通安全、工地监控等领域。
|
2月前
|
存储 算法 网络协议
OSPF的SPF算法介绍:原理、实现与应用
OSPF的SPF算法介绍:原理、实现与应用
89 3

热门文章

最新文章