2024面向对象设计与构造第一单元总结

22373451-郝梓翔 学生 2024-03-23 19:52:31

OO第一单元总结

第一次作业

代码架构

第一次的难度不是很高,但是是第一次接触表达式解析的问题,所以上手时遇到了不小的阻碍。经过往届学长的博客分享和oo公众号发布的推送学习,最终确定了递归下降法作为代码的整体架构。递归下降法的核心就是建立从exprterm再到factor的语法树,作业要求的括号展开就要依据建立的语法树进行计算,所以第一次作业的架构总体分为三部分,第一部分时利用语法解析器lexer建立token流的过程,第二部分是利用表达式解析器parser建立语法树的过程,最后一部分计算将括号展开输出的过程。以下是我第一次作业的UML类图

img

难点分析

个人在第一次作业主要遇到了两个比较大的难点。

第一个难点是理解递归下降的过程。理解这个算法的关键其实就是把整个过程当作是一个建树递归的过程,只不过是在多个函数之间的递归,函数之间有明显的层级关系。
public Expr ParserExpr(Lexer lexer) {}
public Term ParserTerm(Lexer lexer) {}
public Factor ParserFactor(Lexer lexer) {}
递归下降的核心就是这三个函数之间的调用关系,其中public Expr ParserExpr(Lexer lexer) {}函数是最顶层的解析表达式函数,之后调用public Term ParserTerm(Lexer lexer) {}
解析表达式的每一项,最后调用public Factor ParserFactor(Lexer lexer) {} 解析项中的每一个因子,因子有常数因子,变量因子和表达式因子,表达式因子还需要调用最顶层的解析表达式函数,而常数因子和变量因子就是递归终点。

第二个难点就是如何利用语法树进行括号展开。注意到括号展开的结果一定是一个关于x的多项式,我在第一次作业的解决思路利用HashMap容器来存储语法树每一个节点的状态,即每一项x的指数对应的系数,并且在递归回溯的展开计算,从而在建树完成后完成了对每一个节点状态的维护,最后可以根据根节点的状态进行输出。

Bug分析

虽然第一次作业的框架实现没有大问题,但是在强测和互测中还是出现了bug,经过bug修复后发现是最后总结输出的问题。一方面,虽然第一次作业自己有动手写评测机的,但是由于数据覆盖范围没有很广,并没有检查出问题;另一方面成功通过中测后自己并没有很认真的再看一遍代码,导致一个简单的逻辑错误并没有检查出来

第二次作业

代码架构与扩展

第二次作业与第一次作业差别较大,新增加了指数函数和自定义函数,而我的第一次作业并不是能很好地留出这两种因子的扩展。在语法解析方面,新增加了指数函数类型和自定义函数类型,token的类型增加,同时在用lexer解析目标字符串的时候并不是能很好解决自定义函数的实参替换问题,还需要增加新的预处理模块,能够实现自定义函数的实参代换问题;在建立语法树方面,第一次作业三层函数的主体框架已经搭建好,
public Expr ParserExpr(Lexer lexer) {}
public Term ParserTerm(Lexer lexer) {}
public Factor ParserFactor(Lexer lexer) {}
需要扩展的就是两种新的因子解析函数 在计算方面,这是与第一次作业差异最大的地方,由于第一次作业我在计算方面使用维护节点状态的方法实现,在第二次作业很难实现,由于指数函数和幂函数不兼容,无法用一个比较简单的通用状态去存储这两种因子,导致我需要将计算层面重构。经过阅读往届学长的博客,最终采用了建立多项式类(Poly)和单项式类(Mono)的写法,多项式类包含即在建立语法树之后,将整个语法树转换成多项式,最后将转化成的多项式类输出,由于转换成多项式类时从语法树的叶子节点开始,多项式转换完成即完成了表达式的计算以下是我第二次作业的UML类图

img

难点分析

我第二次作业的难点主要有两个,第一个是多项式类和单项式类的建立,另一个就是合并优化的问题。 第一个问题,多项式类和单项式类的建立,多项式类的原理比较简单,其属性为Arraylist<Mono> monoList而单项式类的属性会比较复杂,在第二次作业的架构里面,最小项的形式为

$$ ax^bexp(Poly) $$

因此Mono类的属性应该还有指数内的Poly,而在我第一次思考中,由于并不确定这种嵌套是否合理,就使用了字符串的形式,但这样会给后续合并留下麻烦,最后又改回这种写法。
第二个难题是合并优化问题,由于指数函数,两个Mono能否合并的判断变得复杂,需要在PolyMono类中都要重载isEqual方法,同时isEqual方法的实现也有很多种,我才用的复杂度O(n^2)的暴力比较。

bug分析

第二次作业的bug有点多,导致在强测出现了比较大的问题,首先是对于没有仔细阅读指导书,导致没有处理自定义函数的空白项,出现比较大的问题,另一方面是在解析指数函数因子的时候判断条件有误。有这些比较大的问题,主要原因是第二次作业没有进行足够的测试,而且第一次作业的扩展性很弱,为第二次的实现提高了难度。

第三次作业

代码架构

第三次作业增加了求导因子,同时自定义函数可以嵌套,而第二次作业的架构完全可以实现第三次作业的扩展,只需要增加对应的求导方法,函数嵌套已经可以通过第二次作业的实参替换实现。 第三次作业与第二次作业的主要区别是我主要参考了Java设计的工厂模式和策略模式,并且将各个实现模块进行打包,我分成了三个模块,第一个模块是product模块,包括各种ExprTerm以及Factor,第二个模块是工厂模块,主要是测法解析器lexer和完成语法树的建立Parser,最后一个模块是计算模块calculate,包括多项式类和单项式类,而多项式计算的方法,我全部放入了Strategy类中,将代码分模块打包,可以有效降低代码耦合度,逻辑更清晰。下面是我第三次作业的UML类图

img

总结

oo第一单元的学习结束,自己确实学到了很多知识,但是仍然有很多的不足,比如在数据构造,代码评测方面还有很大的问题,对答案的优化也没有很好的解决方案。导致强测和互测频频出现问题,但是通过学习无论是往届学长还是其他人的思路和架构,都会让我获得很多启发。我会在oo后续单元的学习中继续进步,努力理解掌握面向对象的设计理念。

...全文
101 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧