301
社区成员
发帖
与我相关
我的任务
分享递归下降

读入一个包含加、减、乘、乘方以及括号的单变量表达式,输出恒等变形展开所有括号后的表达式。

数据存储类:
解析类:
++,--,+-,-+,^+,*+简化替换为+,+,-,-,^,*+0-abs(num),将乘一个负数转化为*(-1)*abs(num);读取字符并判断类型,存入tokens中Expr -> Term -> Factor进行递归下降解析计算类:
a*x^b为基本单元计算,并将计算结果通过Factor -> Term -> Expr向顶层传递(Term层完成Factor的乘法运算,Expr层完成Term的加减法运算)。
类复杂度

方法复杂度(截取部分)

Lexer两次遍历字符串(删去前导零、按字符类型将其存入tokens)。
Operation类通过两次按指数大小遍历hashmap对结果进行输出。
Parser类耦合了解析与计算。
^,我在parserTerm中将其替换为...* ...* ...的形式,使得^和*统一起来。Expr、Term、 Factor中均采用Hashmap存储a*x^b中的a与b。-1+x,字符串x-1的长度更短,于是在输出中先输出正数项,后输出负数项。索引值+1,但未考虑索引值+1是否会超出字符串范围。(该问题直至第二次互测时才被发现) 支持嵌套多层括号;新增指数函数因子;新增自定义函数因子。

数据存储类:(其余架构同homework_1)
a*x^b改为使用类存储操作类(预处理、输出):(其余架构同homework_1)
函数类:
解析类:(其余架构同homework_1)
计算类:

类复杂度

方法复杂度(截取部分)

Calculation类完成乘法、加法运算,遍历两个Result、判断其是否相同。
Func类不断遍历字符串直至所有函数名被替换。
Lexer一次遍历字符串(按字符类型将其存入tokens)。
Operation类对字符串进行预处理,多次递归寻找exp(...)的最短输出,并按先正系数项、后负系数项的顺序输出Result。
Parser类进行解析。
exp(...)内括号问题,总结出如下条件:if (该项为常数项) {
exp(...)中的...两侧不加括号
} else if (该项是x或exp(...)) {
exp(...)中的...两侧不加括号
} else {
exp(...)中的...两侧加括号
}
exp((20+30*x+40*x^2)),exp((4+6*x+8*x^2))^5更短,由此根据讨论区同学的想法,我提取公因数,不断比较,使exp(...)的输出尽可能短。exp(...)的输出尽可能短,我不断递归调用获取字符串的同时,时间复杂度增加。exp(...)时,没有考虑到如下情况:exp((3*x+2*x^2+2*x^3+2*x^4+2*x^5)) (34个字符)
<==>
exp(x)*exp((x+x^2+x^3+x^4+x^5))^2 (33个字符)
索引值+1,但未考虑索引值+1是否会超出字符串范围。(本次作业互测环节被hack)新增求导算子;支持调用其他“已定义的”函数。

数据存储类:(其余架构同homework_2)
解析类:(其余架构同homework_2)
函数类:
计算类:
操作类:(同homework_2)

类复杂度

方法复杂度(截取部分)

本次作业只有Func类和Calculation类各增加了一个函数,复杂度分析基本同homework_2。
本次作业所体现出来的优点完全得益于前两次作业架构(尤其是第二次作业)的可扩展性搭建:
exp(...)”的情况,但即便经过很久思考,我也无法找到平衡输出性能和运行时间的实现方法,最终害怕强测互测出现TLE,舍去了这种性能优化,强测第九点又又又涉及这种方式,于是性能分没了……第二次作业互测阶段败在了如下数据,原因是删除前导0时有读取"字符串索引值+1"的操作,但没有判断是否越界。
0
0
做测试时一味追求长、难、多层嵌套的数据,忽略了这类基础数据。
我着重hack了长数据点(包括多层嵌套、超大指数等)、exp(...)内括号问题。但三次hack同房间的同学的代码都很完美,只有第二次作业采用多重exp嵌套hack到了人,下载同学代码发现是TLE问题。
a*x^b项,有效解决数组、Hashmap多层嵌套不直观的问题;自己写数据克隆,有效解决数据类型自带克隆的深浅克隆问题。exp(...)有效输出。凭着OOpre多次迭代的经验,我在写hw1和hw2时就在有意识地搭建结构清晰、可读性强的架构:没有将大量代码堆在Main中,而是建立单独的Operation类,完成预处理和输出;hw2及时将解析与计算解耦,方便第三次迭代。
我在测试部分做的不好,一方面依赖于同学的测评机、自主性不强,另一方面自己构造数据时没有着重构造最简洁、最易错、最麻烦、最大值的数据。
希望能对 exp(...) = exp(...)*exp(...) 这种性能优化提供一些思路orz