码迷,mamicode.com
首页 > 其他好文 > 详细

BUAA UNIT3 社交关系模拟系统

时间:2021-06-02 15:12:46      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:结构   容器   个数   有用   junit   关注   实现   网上   ash   

BUAA UNIT3 社交关系模拟系统

一. 总结实现自己实现规格所采取的设计策略

? 在实现JML规格时,采取的策略为先大致读一遍JML规格,理解将要实现的类成员变量与方法的大致意义,之后去设计将要实现的类中的数据结构与算法,然后开始下手写代码。值得注意的是,这仅仅是第一步要进行的工作。

? 在之后的代码编写过程中,难免不会出现因为对其他类的规格理解不清而产生需要重新阅读JML规格的情况,因为数据结构设置不合理导致重新进行数据结构的选择的情况。例如,由于其中Network类需要对Person, Message, Group 类中的成员变量以及方法都有调用,将其放到最后编写比较合理;而多种Exception类由于编写方法类似,在编写的过程中也不会出现对其他类的调用,放在最初编写比较合理;对于Person,Message,Group类,自然编写顺序排到了Exception之后,Network之前。即编写的优先级为 Exception > Person, Message, Group > Network

? 而在数据结构的设计中,也有需要考虑的地方。比如Network中isCircle()方法的实现,最容易想到的方法自然是DFS或者BFS无脑搜索,但是因为需要考虑性能问题,之后我放弃了这一方法,查阅资料找到了并采用了并查集的数据结构来维护图的连通。在之后的架构中,则采取了在相应的类中维护变量进行操作的方法,比如在Group中维护了sum来防止每次重复进行求和从而导致性能大大降低。

二. 结合课程内容,整理基于JML规格来设计测试的方法和策略

测试策略一: 采用Junit单元测试框架进行测试

? Junit是程序员测试,即白盒测试,因为我们知道自己的程序如何完成功能以及能够完成什么样的功能,同时利用Junit进行测试与我们使用的JML规格有相通之处,同时,启动Junit之后,能够进行自动化测试并判断执行的结果,不需要人为干预,能够减轻我们的工作量。我们只需要根据JML规格给出的方法的实现前与实现后的状态就能够写出相应的 Junit测试框架,从而进行单元测试。另外Junit还能够单独添加、删除、屏蔽测试方法,不影响其他的测试方法,从而能够有效地进行原子测试。

测试策略二: 黑盒测试

? 黑盒测试即不关注内部的实现过程,仅仅检查程序的功能。通过黑盒测试能够覆盖大量的测试样例,但本次作业中的黑盒测试并不像第一次作业表达式求导那样,具备python自带的库能够有效地得出正确结果。因此,很难找到有效的方法进行正确结果的获取,这时有效的方法为两个代码的对拍,因此适用于互测的环节。但是黑盒测试的方法很难针对性地生成边界性的数据,因此虽然覆盖范围大,但是很难保证全覆盖。

测试策略三: 人工构造样例

? 人工构造构造速度比较慢,但是能够针对性地测试边界性的极限数据,因此是对黑盒测试的一种弥补。

三. 总结分析容器选择和使用的经验

? 在最初选择容器的时候,一开始我选择了ArratList,因为操作简单,同时能够动态增长。但是由于对性能的要求,后来改用了查询时间复杂度为O(1)的HashMap。值得注意的是,在实现并查集的时候,因为涉及到对前序节点的查询,而在网上给出的代码中使用了数组实现,因此我在进行编写代码沿用了数组的做法。而由于中测的数据太弱了,并没有出现bug,而在强测中出现了大量的bug,因为Person的ID出现了负数,数组出现了负下标,自然就失败了,于是后来又使用了HashMap。在之后的设计中,为了防止前述情况的出现,均使用了HashMap,HashMap太香了

? 而在本单元在对容器进行选择时,确实考虑了一些问题,在此中总结如下:

  • 选择容器时一定要满足数据的要求,比如如果要用负数当作索引就要避免数组的使用

  • HashMap进行选择时,一定要注意键值对的选择,有时候两者的顺序如何放置都能够完成功能,但是通过对key进行查询速度要快的多

  • ArrayList的本质上是一个数组,但是只能存储一元的数据,有时候想要存储多元的数据时就会显得捉襟见肘,这时候就需要选择Map型容器

    综上所述,HashMap是最终的选择

四. 针对本单元容易出现的性能问题,总结分析原因

本单元容易出现性能问题的地方主要有以下几点:

  • isCirCle()中判断两个点是否连通时,是一个容易出现性能问题的点。因为最基础的方法为采用DFS或是BFS进行搜索,时间复杂度为O(n),可以说没有用什么算法。而如果采用了并查集的方式维护数据,最差的情况为O(n),而最优的情况则为O(1) ,如果在并查集建立的过程中及时进行维护,能够使得复杂度维持在O(1),性能能够大大提高。
  • 在进行平均数计算的时候,如果每次都进行累加,则会有O(n)的时间复杂度,而这之中大部分的过程都是重复的,可以维护一个变量计算Group中当前中的sum,在进行查询的时候仅仅需要简单的除法就能够得到结果,时间复杂度O(1),但是累加的过程中有可能爆int,用BigInteger进行维护就没有问题了
  • 最短路径的求解是性能最差的地方,因为采用Dijikstra算法的时间复杂度为O(n2),而在我的印象里这已经是相当快的算法了。但是这次作业中O(n2)的时间复杂度会TLE,需要进行dijikstra算法的堆优化,时间复杂度为 O(nlog n),恕我才疏学浅

五. 梳理自己的作业架构设计,特别是图模型构建与维护策略

类图如下:

技术图片

? 本次作业的架构设计是由课程组给出的JML规格来实现的,而我主要是利用了Person中acquaintance与value这两个List(HashMap实现)来维护图中的连通关系,即Network中记录了图中的结点,每一个结点中记录了与该结点相连的边的信息。在维护图模型时,仅仅需要对相应的结点进行增删操作,比较简便。但是这种设计方式带来的缺点也显而易见:在进行最短路径的求解时,需要每次进行遍历,从而耗费性能,在之后应当继续考虑新的维护方式。

BUAA UNIT3 社交关系模拟系统

标签:结构   容器   个数   有用   junit   关注   实现   网上   ash   

原文地址:https://www.cnblogs.com/tianyuan2001/p/14824181.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!