第三单元总结
第三单元总结
第一次作业
本次作业思路
- 认为本次作业难度主要为
isCircle
和queryBlockSum
- 在完成
isCircle
的时候主要是使用了查并集的方法,使用了一个全局变量HashMap
来维护这个函数的实现,其中的key
为每个人的id,value
是每个对应id的人的最终的父节点的id。每次增加人时,其父节点是他自己。当addRelation
时将第一个变量的id的最终父节点的父节点改为第二个变量的id,从而实现查并集。此外还在实现查并集的时候增加了压缩路径的方法,即在每次遍历父节点时记录起点和终点,再次遍历修改遍历过程中每个点的父节点。 - 在
queryBlockSum
的处理中,由于使用了查并集和压缩路径的办法使得处理起来十分简单,利用了一个整数容器来记录最终的父节点,然后遍历所有成员的父节点,所拥有的的不同的父节点的个数即函数所需要返回的值。
- 在完成
本次作业的bug
- 在处理
isCircle
函数时,一开始并没有直接使用修改父节点的办法,而是对于各种情况进行讨论判断,使得在函数处理的过程中会出现存在三个点的父节点成为一个三角形互相指向的情况,导致在使用查并集便利时出现死循环的情况,最后经过思考才发现只需要修改其父节点即可。
第二次作业
本次作业思路
- 本次作业的难点主要为实现
queryLeastConnection
函数。- 为了实现该函数新增了一个类
Edge
用于记录每一条边的起点、终点以及权值,在每次使用AddRelation
时记录。其次使用了一个HashMap pointer
来记录已经存储的符合条件边的两个端点,且和上次作业的isCircle
一样来重新记录其父节点为自己,以及使用变量int sum=0
作为返回值。随后调用该函数时,现将存储着边的容器根据权重由小到大进行排序,随后遍历。由于本函数的意思为计算含有输入变量id的图中的最小路径,所以首先使用上次作业所完成的isCircle
函数来判断边的其中一个端点是否和id的点在一个图中,如果在一个图中,判断两个端点的父节点是否为同一个,如果两个端点的父节点不同那么sum+=value
,并且修改其父节点为同一个。
- 为了实现该函数新增了一个类
本次作业bug
-
在刚开始实现
queryLeastConnection
函数时,想法过于简单导致出现了bug。在最开始的想法中我只记录了端点,如果一条边的两个端点都被记录那么该边就不会被使用。但是后来的测试中发现该算法会出现一个问题,比如-
存在四个端点,1 2 3 4,其边的权值从小到大分别为1->2 3->4 2->3 上述算法中就会出现一个问题,在记录前两条边后四个节点都会被记录,导致2->3该边无法被记录
-
-
还有一个很弱智的bug,在一次作业中部分异常的抛出需要排序,我实在调用抛出异常之前来进行排序再输入的,在第二次作业时忘记了。后来觉得第一次作业的做法实在愚蠢,自己还是没有改变编程的思想,还是处于面向过程的编程的思维过程中。
-
在互测的时候
queryValueSum
出现了一些tle的情况,在弱测提交之前听说过这种情况,但是以为强测不会检测所以没有认真去优化该函数,结果互测中被hack了好几次。一开始是想的用变量来记录函数结果,且记录是否需要修改即可。但是助教打回了这个修改,后来发现确实由于该修改只能保证部分数据能够过关,但是没有普遍性。随后Goup
类中使用了一个变量来进行维护,在addRelation
时就进行了该结果的修改使得调用函数时直接返回即可。 -
在互测过程中还出现了一个哭笑不得的bug,被同学们的测评机给测出来了。当时和同学对拍时有一个bug改了很久,后来发现是group的id为79的时候出现的,所以为了方便调试增加了关于该情况的特殊判断的输出,在最后提交的过程中注释了,但是提交的版本忘记更新了,最终导致出现了问题。
第三次作业
本次作业思路
- 本次作业的难点主要是实现
sendIndirectMessage
- 这个函数的意义是实现从一个用户到另外一个用户的最短路径。(
感觉逐渐数据结构化)这个题目大致的思路是有的,但是上次作业卡tle卡出ptsd了,一直在想是不是存在优化的算法。最后查看了助教在讨论区发的帖子,明白了大致的优化思路,而且在助教优化的思路上我将判断结束的条件改为了是否为要到达的id。
- 这个函数的意义是实现从一个用户到另外一个用户的最短路径。(
本次作业bug
- 在刚刚实现
sendIndirectMessage
的时候没有很明白助教的思路的意思,导致自己在更新权重的时候更新的地方出现了一些问题,最终使得提前的break
使得计算错误,最终看同学的代码才明白自己哪里有一点问题。 - 在和同学对拍的时候发现自己的部分代码出现异常的情况,原因是在处理
dce
时忘记将对应的message给删除,导致部分情况在HashMap
中会用get
出现了得到的是null
的情况。 - 在分发红包的过程中,将分发红包的用户也发了钱。
- 在本次作业的删除中,虽然使用的是迭代器的办法来进行删除,但是由于迭代器的使用不够熟练仍然出现了抛出异常的情况,最终使用的是用另外一个容器来记录不用删除的元素最终更新容器的办法来实现了元素的删除。
测试数据的准备
- 第一次作业测试数据的准备主要是围绕自己在写的过程中出现的三个点的父节点成为一个三角形互相指向的情况制造了一些数据点。
- 第二次作业主要是出现了聊天群中的人数不能超过1111,以及存在部分同学没有维护变量导致tle的情况(虽然我的数据点没有卡成功)
Network扩展
- 消费者订阅广告商
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == id2) &&
@ (\exists int i; 0 <= i && i < advertisers.length; advertisers[i].getId() == id1) &&
@ getPerson(id2).hasAdvertiser(getAdvertiser(id1)) == false;
@ assignable getPerson(ide2).advertisers;
@ ensures (\forall Advertiser i; \old(getPerson(id2).hasAdvertiser(i));
@ getPerson(id2).hasAdvertiser(i));
@ ensures \old(getPerson(id2).advertisers.length) == getPerson(id2).advertisers.length - 1;
@ ensures getPerson(id2).hasAdvertiser(getAdvertiser(id1));
@ also
@ public exceptional_behavior
@ signals (advertiserIdNotFoundException e) !(\exists int i; 0 <= i && i < advertisers.length;
@ advertisers[i].getId() == id1);
@ signals (PersonIdNotFoundException e) (\exists int i; 0 <= i && i < advertisers.length;
@ advertisers[i].getId() == id1) && !(\exists int i; 0 <= i && i < people.length;
@ people[i].getId() == id2);
@ signals (EqualadvertiserIdException e) (\exists int i; 0 <= i && i < advertisers.length;
@ advertisers[i].getId() == id1) && (\exists int i; 0 <= i && i < people.length;
@ people[i].getId() == id2) && getPerson(id2).advertisers(getAdvertiser(id1));
@*/
public void addAdvertiserToPerson(/*@ non_null @*/int id1,int id2) throws advertiserIdNotFoundException e,PersonIdNotFoundException,EqualadvertiserIdException;
- 消费者查询某广告商的商品价格
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == id1) &&
@ (\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length; commodities[i].getId() == id2)
@ ensures (\forall commodity i; \old(getAdvertiser(id1).hasCommodities(i));
@ getAdvertiser(id1).hasCommodities(i));
@ ensures \old(getAdvertiser(id2).commodities.length) == getAdvertiser(id1).commodities.length ;
@ ensures \result == getAdvertiser(id1).getCommidity(id2).price;
@ also
@ public exceptional_behavior
@ signals (advertiserIdNotFoundException e) !(\exists int i; 0 <= i && i < advertisers.length;
@ advertisers[i].getId() == id1);
@ signals (CommodityIdNotFoundException e) (\exists int i; 0 <= i && i < advertisers.length;
@ advertisers[i].getId() == id1) && !(\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length.length;
@ getAdvertiser(id1).commodities[i].getId() == id2);@/
public int addAdvertiserToPerson(int id1,int id2) throws advertiserIdNotFoundException,CommodityIdNotFoundException;
- 消费者购买产品
/*@ public normal_behavior
@ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == personId);
@ requires (\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == advertiserId) &&
@ (\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length; commodities[i].getId() == commodityId)
@ ensures getPerson(personId).money = \old(getPerson(personId).money) - getProduct(commodityId).getValue;
@ ensures getSaler(advertiserId).getProduct(commodityId).getLeftNum() = \old(getSaler(advertiserId).getProduct(commodityId).getleftNum()) - 1;
@also
@ public exceptional_behavior
@ signals (PeronIdNotFoundException) !(\exists int i; 0 <= i && i < people.length; people[i].getId() == personId);
@ also
@ public exceptional_behavior
@ signals (PeronIdNotFoundException) (\exists int i; 0 <= i && i < people.length; people[i].getId() == personId)&&!(\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == advertiserId);
@ also
@ public exceptional_behavior
@ signals (commodityIdNotFoundException) (\exists int i; 0 <= i && i < people.length; people[i].getId() == personId)&&
@(\exists int i; 0 <= i && i < advertiser.length; advertiser[i].getId() == advertiserId)&&
@!(\exists int i; 0 <= i && i < getAdvertiser(id1).commodities.length; commodities[i].getId() == commodityId) ;
@*/
public /*@ pure @*/void purchaseProduct(int personId, int commodityId, int advertiserId) throws PeronIdNotFoundException, commodityIdNotFoundException;
作业感想
- 本次作业主要是学习了语言规格的用法,对于语言的规格我认为主要是为了规范代码的内容从而实现预期的目标。在浏览规格代码的时候会发现很多是我们觉得很“废话的语言”,但是正是这些“废话”保证了某些元素的不可变性,使得语言更加规范,没有牛角尖可钻。
- 在本次的作业中测试主要是和同学进行对拍(
因为弱测真的很弱,第一次作业的弱测大部分就只有一条指令hh),在和同学的对拍过程中发现了一些问题,也帮同学发现了自己的问题,在对拍的过程中也进行了一些函数的算法交流,获得了一些不同看问题的角度,最终不断完善了自己的代码。