301
社区成员
发帖
与我相关
我的任务
分享queryTripleSum方法。其数据构造策略相对简单,我设计了K(5,5)完全图、完全图删几条边以及非连通图等几个不同的情况。其实还是通过手动构造样例去尽可能地覆盖更多的可能。queryCoupleSum方法。本次作业需要设计更多的样例以覆盖,增加了全是孤立点的情况。这次作业也让我意识到前一次作业在数据构造方面的不全面性。deleteColdEmoji方法,由于本次作业增加了消息类,总体更加复杂,因此手动构造样例的方法难以覆盖所有情况。因此在这次测试中,我采取了“手动+随机”的构造方法。addPerson和addRelation均为手动加入指令,随后在表情的数量、总消息的数量、消息被send的数量、limit均利用了随机数进行生成。增大testNum,可以较全面地覆盖到大多数情况。本单元的作业的架构设计是以课程组给出的官方包为基础展开的。
在MyNetWork中,采用HashMap存储Person节点,每个Person都有自己的aquaintance数组,总体上形成的是邻接表式的无向图结构,此外,每两个Person之间的value代表图中这条边的权值。
isCircle:如果直接实现,需要在每次调用此方法时使用dfs,会极大地增加时间开销。因此可以采用并查集进行实现。并查集,即利用一个HashMap记录每个结点的父节点。并查集的维护如下:
addPerson时,将这个人的父节点设为自己;addRelation时,将一人的根结点设为另一人的根结点的父节点;modifyRelation时,如果遇到删边的情况:如果在删边之后两点不再连通,那么分别将两点各自所在的连通图的所有节点的父节点设为自己;反之,则直接把连通图所有节点的父节点设为两点的其中一个。public int getRoot(int id) {
if (id != union.get(id)) {
union.put(id, find(id)); //即路经压缩,其中find方法的作用是寻找结点的根结点
} return union.get(id);
}
在调用isCircle方法时,只需比较两点的根结点是否相同即可。
queryBlockSum:这个方法的本质是求连通分支的个数。可以设置全局变量进行维护。在addPerson时,该变量加一;在addRelation时,如果两点本来不连通,该变量减一;在modifyRelation删边时,如果删过边之后两点不再连通,则该变量加一。
queryTripleSum:如果直接按JML语言实现,需要使用三重循环,时间开销太大。因此设置全局变量tripleSum,在每次addRelation加边以及modifyRelation删边的时候,通过遍历所有人,找到两点共同的熟人,对变量进行维护。
queryAgeMean与queryAgeVar:需要在MyTag中设置属性ageMean,每次加人或减人时对其进行维护,求解时直接调用该变量即可。
queryBestId:在MyPerson类中设置属性bestId,在addRelation与modifyRelation时对其进行维护。addRelation时,通过和原bestId的value比较确定是否需要更改;modifyRelation时,如果原本的bestId是对方,则需要通过遍历确定来新的bestId。
queryCoupleSum:直接实现需要两重循环。在具体实现时,可以采用只遍历一遍的方式,找到某个人的bestId后再确认他的最佳好友的bestId是否是他自己,如果满足,结果就加一。
getValueSum:如果直接实现,需要采用两重循环。因此可以考虑采用全局变量维护:
MyTag的addPerson和delPerson中,需要遍历Tag中的所有人,将全局变量按照每个人与指定人的value进行2倍的增减。addRelation时,遍历找到两个人共同的熟人,然后修改他们tag中的valueSum变量;modifyelation时,同addRelation一样。但注意如果遇到删边的情况,对valueSum减少的不是参数value,而是两人原来的queryValue值。queryShortestPath:采用bfs广度优先搜索即可。
本次作业在性能提升方面并无太多的要求。有一个点需要注意:在MyPerson中,可以采用LinkedList存储messages。
MyTag中设置属性ageMean,每次加人或减人时对其进行增减,求解时直接调用该变量即可。规格给出了某个方法需要实现的目标与规范,但是实现时并不一定需要根据规格逐字逐句编写程序,只需要保证最终的结果满足规格中的所有要求即可。比如,在本单元作业中,JML语言给出的是数组(类似于ArrayList)形式,而在实现时大多都采用HashMap存储,最终达成的效果是一样的,只不过实现的方式可以提高性能。
\assignable允许修改的内容,对于明确\not_assigned的内容,应严格检查其是否被修改;pure标记的方法,需要检查这个类在调用方法前后是否严格一致;\ensures是否得到保证;本单元的学习相较于前两单元轻松了一些。学习完本单元之后,我熟悉了JML语言,了解了规格在编程中的意义。但我感觉,本单元的作业相较于对规格的理解,在算法上的要求更高,我也从中温故了数据结构与算法的相关知识,感受到了维护策略带来的便利。希望在以后的学习中,能够更加深入地理解规格的意义,同时也要不断提升自己对于各种算法的运用能力。