1.JML规格设计策略

  我三次作业采用的方法都是从性能与存储大小方面考虑。在满足规格的条件下尽量做到运行速度最快,所用空间最小。因为这个单元的作业如果单单只是照着jml规格来翻译的话就失去了意义(因为我太菜了没写测评机啊啊啊啊啊)。

  本单元内容是根据给定的规格实现一个可以实现个人操作,好友关系操作,群组操作,收发消息等的社交网络。我写这个单元的时候,首先是写 Person 这个类, Person是这个单元最基础的类,和其他的类几乎没有牵连,故可以最先完成。每一次进行迭代的时候,我都将两次的规格进行文本对比以找出这所更新的,再来添加这些新的东西。写完 Person后写 Group、 Message等类,这个是只用到 Person的,之后再写 Network,这个是整个代码的核心。最后再完成异常类的编写。

  在具体的类的实现中,我首先是将所有的规格代码都看一遍,以此来选择最合适的容器来设计。在参考了一些同学的方法后,我优化了一些函数,像异常类出现频率高的直接整合成一个函数来调用,以及使用了一些已存在的函数(避免自己造轮子)。

2.测试方法和策略

  这次的测试方法主要还是根据jml规格来。阅读jml的代码,考虑每一句的极限情况,以此来构造边界数据。从理论上来说只要每一步都是正确的,那合起来肯定没问题,但是在实际的测试中发现其实很多情况对单独的一条限制来测试是不够的,因为也许会有其他的语句隐性地限制了,所以还是要阅读一整个方法的规格,综合起来考虑边界情况来测试。不过只要是写的满足了规格,在测试中就不会出错,这个单元重点就在认真阅读jml代码。

  测评机就没写了,自己构造了数据手跑和同学的进行对比。

3.容器的选择和使用

  这个单元的容器主要是 Hashmap。这是基于对速度的考量,而且三次作业的所有类的id都是唯一的,这也是一个很好的使用 Hashmap的条件。怎样选择容器,其实质是基于对jml规格代码的理解。在第一次作业的queryBlockSum函数中,其jml规格代码有用 Person与该 Person之前加入的所有 Person是否有相连关系,这个当时我就认为是和 Person的加入顺序有关的,于是在 Network中 Person这个我使用了Arraylist.直到参考他人的代码时才发现原来可以用 Hashmap,这个函数就是求联通分量的,而且这也是可以通过离散来证明的,果然还是基础学科没学好。

  我使用 Hashmap大多时候是建立一个id和对象的索引,不过在解决联通块问题时,也使用了 <Person, Person> 的哈希键值对,也是为了建立人际关系。另外其实在 Hashmap中,有许多已经造好的轮子,比如merge函数,这个函数实用性非常强,可以大大简化代码,估计性能上没太大的影响。还有就是compute函数,重新计算并返回新的值。我还是对java不太熟悉,感谢给我参考代码的同一个房间的同学!

4.性能问题

  第一次作业第一个性能问题就是每一个查询操作不能遍历,使用 Hashmap就可以解决这个问题。第二个性能问题是对于联通块的计算。在第一作业中,我的iscircle函数直接写的dfs,dfs搜到就立马退出,然后计算联通块也是完全照抄规格来写的,强测没有超时,但是被同房的同学hack超时了,在参考完同学代码后,使用了一个类似找出一个联通块的根的方法,创建了一个<Person, Person>的哈希表,同时定义了一个btc变量来记录联通块的数量。每次有people加入,btc++;每当有addRelation就btc--,同时寻找到根,将people与根相连。这样一来查询联通块直接返回btc,复杂度为O(1)。而iscircle的话直接比较两者的根是否相同即可。

  第二次作业的话主要是对求年龄平均数与标准差的计算,这个也是不能最后遍历求和啥的,得先定义一个变量来存储年龄和,年龄平方和。最后在对规格中给出的表达式来化简求值。主要是要注意精度问题,要严格按照规格来。对于getValueSum这个函数似乎没有好的化简方法,复杂度为O(n^2)。因为可能有删除person的操作,如果也事先记录的话,这个删除也会是O(n^2),并不会有化简。这个函数我选择每次只遍历没有进行比较过的,也只是少了一半的时间。

  第三次作业的话主要是最短路径的查询问题。我是用的是堆优化的Dijkstra算法,并且每查完一次都记录先来了(如果增加了新的关系就作废)。在这条路线上的所有点之间都是最短路径,尽量减少查询的次数。

5.架构设计

  本单元完成了一个基本社交网络的模拟,最基础的类为 Person,该类就是图的节点,之后各种各样的类也是围绕节点展开,节点之间存在联系,即构成边,并赋值为value。同时还存在 Group这种结构可以保存多个 Person,以及相应的数据内容。除此之外还有 Message 的结构可以实现人与人直接,人与组织之间信息的传递。最后 Network类将之前的各类联系和囊括在一起,保存了之前各类存在的信息。

  关于图的维护,主要是对节点和边的增删。主要有addPerson、addRelation等函数。在编写这些函数的时候,需要考虑到自己所有的容器,他们是否需要改变。比如在维护查询联通块的函数中,addPerson需要对联通块数量增1,addRelation则需要对联通块数量减1,同时更新根节点与节点之间的关系。在查询最短路径时,在这两个函数中都要及时维护边与节点的数量关系等等。

最新文章

  1. Hibernate一对一、一对多、多对多注解映射配置
  2. mysql TIME_WAIT
  3. 利用MDK4中的逻辑分析仪分析IO口的PWM波
  4. 物联网操作系统HelloX已成功移植到MinnowBoard MAX开发板上
  5. 删除Windows右键不用的选项
  6. 黑马程序员_Java集合Map
  7. 基于Jquery的多彩二维码的生成
  8. VS2012下基于Glut OpenGL glDepthMask示例程序:
  9. jQuery扩展函数设置所有对象只读
  10. 【知识整理】这可能是RxJava 2.x 最好的入门教程(一)
  11. Android自定义视图四:定制onMeasure强制显示为方形
  12. Kafka学习之路 (三)Kafka的高可用
  13. #HTML 块级、内联、内联块级元素
  14. WordPress主题开发:制作面包屑导航
  15. 雷林鹏分享:Ruby 注释
  16. axure可用密钥
  17. PIE SDK同态滤波
  18. SNMP协议介绍
  19. exist &amp; in
  20. Oracle的RBO和CBO

热门文章

  1. antdVue--Upload使用
  2. PHP 阿里云短信验证码的实现
  3. macOS 常用键盘快捷键大全
  4. JAVA随机获取集合里的元素
  5. 安装filebeat
  6. 一个线程池的c++实现
  7. 1903021126-申文骏-Java第十一周作业-Java中继承、多态及抽象类的使用
  8. react实现转盘动画
  9. qt的窗口
  10. C#——》创建Windows服务,发布并调试Windows服务