OO第三单元总结

总体策略分析:

完成本单元作业我采用的是“先整体,后局部”的方式,即实现每一个类之前先读懂JML代码理解各个方法的作用和实现要求,然后再构造类的成员和方法。通过JML可以看出,有些类的实现需要特殊的数据结构成员(如HashSetHashMap等),由此可以在着手写代码之前做到心中有数。

例如Network中JML描述的emojiIDListemojiHeatList在每个方法中都有长度相等的特征,于是选择了HashMap作为容器

对于异常类,使用一个静态整型变量表示异常发生的总次数,同时使用HashMap记录各个id触发的异常数。

测试的方法和策略

由于这个单元的中测样例相对简单,每次在完成作业时都没有找到比较有效的方法,但依然尝试使用了指导书给出的JUnit测试:

测试结果:

各次作业分析

第一次作业

类图:

各类容器选择

第一次作业需要实现的是MyPersonMyNetwork类,对于由于MyPerson中value和acquaintance的一一对应关系,我选择使用HashMap容器。对于MyPerson中的people[],选择使用简单的ArrayList

对于异常类在总体策略分析中已给出,这里不再赘述。

细节分析

第一次作业相对简单,主要难点在于实现MyNetwork中的iSCircle方法,该方法用于检测id为id1和id2的两名用户之间是否存在通路,JML描述如下:

理解了该方法的作用后第一时间想到了深度优先遍历算法(DFS),为了保证各个节点的遍历,为了图省事也选择了递归调用自身的方法,这也导致了此方法在面对海量的节点时耗费时间显著提升,也成为本单元一直困扰自己的问题之一。

第一次作业中isCircle的构造显然没有得到慎重考虑,对于visit数组何时需要清空没有正确认识,导致节点增多的时候程序性能陡然下降,此后虽然在强测中对此方法进行了改进,但还是在性能上拖了后腿

第二次作业

各类容器选择

第二次作业需要实现的是MyMessageMyGroup类,此次并无使用复杂容器的需求,MyGroup中的people[]MyNetwork中新增的messages,选择使用简单的ArrayList

类图:

细节分析

第二次作业新增了MyGroupMyMessage及其附带的异常类,由于此次作业新增的方法复杂程度不高,但需要我们仔细地观察规格,比如此次MyNetwork中新增的方法addtoGroup:

其中要求id为id2的小组能够添加id为id1的新成员当且仅当小组成员数不满1111,如果忽略这个条件就可能得到错误的结果(即使不判断group大小都能过中测),可见本单元需要耐性细致地读懂JML

第三次作业

类图:

各类容器选择

这一次新增了特殊的Message MyEmojiMessageMyRedEnvelopeMessage类,由于需要保证emojiIdemojiHeat一一对应,使用HashMap

细节分析

本次作业实现比较棘手的方法是MyNetwork 中的sendIndirectMessage,要求发送指定id的message,与sendMessage不同的是sendIndirectMessage在两个不直接连结的结点之间发送信息,并返回连接两节点的最短路径长度,为了得到最短路径,我使用的是Dijkstra算法实现,通过标记确定结点visit[]和各个结点相对起点的最短路径长度djlist[]逐步确定最短路程。

作业架构设计

本次作业主要一个难点就是各个用户和关系构成的图的实现。体现再MynetworkisCirclequeryBlockSumsendIndirectMessage方法的实现。虽然上课时老师也提到了涉及图算法,但思来想去,感觉如果构造前再深思熟虑一下,有些方法其实并没有想象中的那么复杂。

比如对于每一个Person,可以构造一个容器收集与其同一个块的Person的id,isCircle中直接再该容器中检查两个id是否位于同一个块。但自己担心每次加入新Person或新Relation时都需要对各个块进行检查并更新各个Person的容器,可能带来新的问题或复杂度,再加上也想训练自己的图算法,导致这个想法最终作罢。

感想与体会

本单元算是自己完成比较顺利的一个单元,但强测却惨不忍睹,主要的问题还是自己读JML代码时粗心大意,而且总是过了中测后就松懈,没有继续检查bug的毅力。希望最后一个单元继续加油!

posted @ 2021-05-31 10:09  DaiWei06  阅读(56)  评论(0)    收藏  举报