BUAA_OO_2020_第一单元
Part 1.作业及评测分析
第一次作业
类图:
结构分析:第一次作业只有一个多项式,故我把类的关系分成了多项式类,项类和求导类,多项式类负责处理输入输出,对多项式完成截断处理,将截断的字符串传入项类进行处理,在项内完成对前系数以及指数的读入处理,完成项的构建,构建项之后在多项式类中我才用HashMap存储项,这样可以快速寻找到同类项,完成合并。
复杂度:
复杂度分析:在print时模块的设计复杂度极高,由于没有在poly中采用重写toString方法,在多项式类中采用了大量的数据交互和判断,导致模块之间的耦合度高,这是设计上的一次失败。
评测:
第一次作业比较简单,评测并没有出现bug,同时因为采取了合并同类项,优先输出正项,对于1和-1的特殊处理等手段,性能比较高,在强测中拿到了满分
第二次作业
类图:
结构分析:第一次作业处理中,将constantx**pow看成了一个整体,在加入了sin(x)和cos(x)之后,这个架构显然显得力不从心,也是因为重新加入了两个因子,我开始对表达式进行了重新的认知,表达式的构成为:项+表达式,而项的结构可以看成因子项。而且第二次作业中没有括号的存在,所以项可以看成基本因子的连乘。
而基于这些特性,在第二次作页我产生了一个取巧的方法:项与项之间一定是通过加减号来划分,那么我能不能通过将加减号做特殊处理,从而可以直接用Scanner类来处理呢,接下来我罗列了几个表达式,寻找表达式之中加减号的特征,我发现凡是用来区分项的加减号前面不是乘号,所以我首先合并了多个的加减号,之后处理了前面不是乘号的加减号,使用Scanner类直接读取,完成了项的划分,之后在项中,我发现,乘号划分了因子,故技重施,完成了基本因子的划分。
接下来便是对基本因子的处理,这次我采用了接口的思想,减少了代码的重复性。
最后将一个项划分为四元组,这次我吸取了上次的教训,在项类中重写了toString方法。
复杂度:
这次的输出复杂度明显得到了改善,但是由于在写完之后才想去化简,导致化简这个类的添加比较突兀,也导致其耦合度比较高。
谈谈化简:
这次作业的长度有限制,我分析最大项数不会超过50,所以我取巧的采用了三重循环,结构是首先找到具有相同的x**pow的项,将其划分为一个表达式类
循环结构:
所有的表达式类
表达式类中的每一项
在表达式类中寻找可以化简得项进行处理,直接将被处理项的系数化为0,防止出现循环处理现象
这样的话,其实仔细分析,发现复杂度如下x(n-x)(n-x),x为表达式类数量,所以可以保证不会出现tle的现象,但是由于循环迭代层数过多,导致复杂度飙升。
评测:
这次评测中强测通过了所有的测试点,但是由于小于等于10000被误理解为小于10000,导致边界数据出错,惨遭5刀。
在互测中,使用了评测机加边缘数据手动评测联合的方法,找到了两个人的bug,而且发现了一个用static方法一main到底的同学,我笃定ta一定会有bug,但是没想到多次评测都没有找出问题数据,也没有采用通读ta的代码的方式寻找bug。
找到的bug:
1.爆栈
2.化简时出错,只处理了一个项,另一项搁置
第三次作业
类图:
结构分析:这次作业中由于迭代结构的产生,导致前两次作业取巧结构的覆灭,在处理输入上我也陷入了困境。
经过仔细分析表达式发现表达式依旧可以像第二次作业那么想像,只要把表达式类也当作基本因子处理即可解决嵌套问题,但是关键在于,因子的处理。由于不想采用转换为char数组再处理的方法,仔细查看了String的文档,发现了两个极其有用的函数,charAt和subString,采用这两个函数,极大程度上显现出了String类相较于字符数组的优势。同时采用了树结构构造Item(项)类,实现了递归求导。同时也实现了判断WORNG FORMAT和读入处理的一体化。在读入处理时完成了合并同类相,例如:
x*x*x*x
sin(x)*sin(x)**2*sin(x)**3
1*x*2*x**3*sin(x)*cos(x)*sin(x)**2
实现了这些基本因子的合并,在递归求导的过程中也实现了1,0等特殊结果的化简处理。
复杂度:
由于在自己测试的过程中,发现了迭代层数过多导致tle的显现,所以代码经过了几次比较大的修改和重构,导致代码结构面目全非,代码也是越写越难看,在BracketDeal类中,甚至出现了四重判断迭代的丑陋代码,导致复杂度飙升。
评测:
这次强测中没有发现问题,但是由于某些tle情况处理仍未达标,在一些多重嵌套的过程中再次出现了tle的现象,而在处理别人代码的时候,采用评测机,但是忽视了空格和制表符的作用,在生成的数据中没有空白字符,漏判了组中一人将正确格式误判为WORNG FORMAT的情况,导致失分。
Part 2.对比
在和别人的对比中,显著的几个问题:
多重迭代判断和多重循环的出现:导致自己的复杂度很高,而且不利于维护;
在化简时很多情况没有考虑,而在第三次作业中由于采用了递归的结构。很容易导致超时,所以在限制了化简的手脚,大幅删减了化简代码
几次作业的迭代非常差,每次新作业都需要重构,后瞻性和可拓展性差
Part 3.感受
在这几次作业中,对面向对象逐渐有了自己的想法,甚至开始觉得采用c语言或者是一main到底很难实现想要的功能,感受到了面向对象式开发的优点
同时也认识到了自己的不足,每次作业迭代极差
也感谢CheckStyle的使用,让我认识到了许多先前存在代码风格问题,也锻炼出了驼峰命名法的使用,在if和for/while的结构也更加美观