当前位置: 代码迷 >> 综合 >> 软件构造 Lab2 Blog-4
  详细解决方案

软件构造 Lab2 Blog-4

热度:51   发布时间:2023-11-17 09:06:55.0

软件构造 Lab2 Blog-4


写在最前面

这次的Blog主要是来写Lab2的一些体会和经验之谈,最初写下这篇Blog的时候,是在刚刚验收过之后,对于自己过去两个星期完成的实验记录最清晰的时候。虽然这次实验总体来说难度依然不是很大,但是相比第一个而言,确实难度上升也比较明显。主要体现在大量的注释的书写相比以前的要求更高,也更加的麻烦。主要理解和书写的难度前两个问题而言,还不是很大,主要在于第三个问题的理解和设计,这不由得让我对下一个星期的实验有了一些畏惧感(Lab3已于2018/3/28 更新实验手册,长达20页)。增加部分关于P3的细节问题

P1 Poetic Walks

对于这个问题的书写,其实难度主要在于理解Graph<L>的和对于泛型编程的熟悉情况。如果理解了题目的要求,书写起来的难度也并没有特别的高。在最开始我写第一个任务的时候,其实对于这个理解还是有不小的偏差的。好在后来发现的比较及时。要论其中书写最难的应该是注释,如何写好大量的注释,分别调理清晰的表示好各个要求,难度很大。尤其是大部分的书写是相比课堂更早的时候,这样对于一些概念的理解可能随着课堂上的进行有些许的偏差,还需要再不断的修改。
其次,对于Code本身,难度主要体现在set的写法和泛型编程。对于set来说,ConcreteVerticesGraphConcreteEdgesGraph两个具体的接口实现类来说,都是其中最难以书写的函数。需要注意多种情况的组合和最好的判断过程,使代码更简单也更容易发现错误(由于这个set函数的书写,不可避免的有多个的if-else判断,所以了解Debug的重要性再一次体现出来)。但是对于泛型编程而言,难度不是体现在具体代码的书写 ,而是了解泛型编程的要求,这一点在以后的学习中(尤其是代码的复用中有显而易见的好处)
综合来说,Poetic Walks难度适中,对于理解ADT和OOP编程来说相当有好处。

P2 Re-implement Social Networks

对于Lab2中的这个问题,主要在于如何复用已经写好的“轮子”,而不是重零再造,学会使用已有的代码,是这个任务的目的所在。在这个任务的实现中,我选择使用的FriendshipGraph类是继承ConcreteEdgesGraph类实现的(在这里我不选择使用ConcreteVerticesGraph类的原因在于,我实现ConcreteVerticesGraph的方法过于暴力,导致整体的效率不高)。在确定复用代码之后,其实主要的问题就是如何合理的使用已有的轮子。比如在搜集两个人直接的最短距离的时候,我可以合理利用已有的Graph接口中给出的targets函数来寻找邻接的节点。这样就可以在尽量多的使用已有代码和尽可能不改变已有的Main客户端的要求下实现P2,总体来说P2的难度相比P1小一些。

P3 Bus Network

对于这个问题,感觉这应该是CMU的一个阶段的作业作为我们一个实验中的一部分存在的,所以难度比前两个要高出不少,尤其是其中的一些设计,CMU在其homework中并没有明确的说明。这就为理解它的任务要求铺设了很大的障碍。其次,由于这个实验要实现的功能相比前两个也要更高一些,需要设计一些接口来规范Spec,并且合理地使用继承来规划各个类之间的关系,这样的难度其实更高。
在这里,由于是基于图的算法,所以如何建图在这个实验中显得尤其重要,加上一个MaxWaitLimit的限制,最多的等待时间不能超过20分钟,导致了一种很奇葩的解法的存在,见下图的公交线路(手残见谅)。
BusNetwork
在上面的那个公交网中,如果我选择从A出发去往C地,出发时间为25000,那么对于我来说最短的用时线路是,从A坐Bus1去往B,在B重新乘坐Bus2回到A,再从A坐车去往C。这样的时间是最短的。避免了等待过长时间(其实本质是把等待的时间换成了公交车上“浪费“的时间)。由于这种超奇葩情况的存在,就限制了我们建图的方式只有将每一条公交线路的每一个停靠车站作为一个顶点,这样才能合理加边,加边的策略是相同的地点不同的车次增加有权边表示等待时间,相同车次不同地点之间增加有权边表示行驶时间。这样的建图策略虽然比较麻烦,但是能够合理的解决问题。实现算法的时候,就需要注意我可能有多个出发顶点(在某个时刻出发并在合理等待时间的顶点较多),那么我可能需要多次的Dijkstra进行比较,找到最短用时的线路,并返回给用户。

另一种奇葩问题的存在
同样由于等待的时间不能超过20分钟,所以其实除了第一站可以出现连续等待之外(由于出发时间和坐上第一辆公交车的时间之间的差值,可能存在连续两次的等待,在现实中等待仍然表现为一次等待,仍以上图为例,乘客在26000时从A地出发,去往C地,那么连续两次等待的意思即为等待bus2的到来和等待bus3的到来,这种问题是由于我对于出发站的处理问题,如果将出发视为第一次做公交车,那么不存在任何两次的连续等待),我们不能有其余的连续两次的等待,那么换句话说最短路上的顶点是有限制的,不能简单按照最短路来处理。比如下面这个图所描述的公交路线(此处感谢chf同学的帮助)
busSegment2
我们可以看到的,在0时从A地出发去往B地,图中的最短路可以看到是A1->A2->A3->B3,但是这种最短路首先不符合等待时间不能超过1200s的限制,再次其根本的原因是出现了连续两次等待,所以在处理的时候需要注意不能够连续等待,需要对Dijkstra进行一下改变以适应。

写在最后

总体来说这次实验写的时间还是偏长了不少,第二周的效率相比第一周下降了不少,尤其是在面对自己不确定问题的时候(P3),容易陷入一种僵局,想法也变得十分停滞。跟超强的D同学还是有不小的差距,希望自己以后可以提高效率,尽量避免陷入死循环之中。

  相关解决方案