BUAA OO UNIT3 社交网络单元总结

BUAA OO UNIT3 社交网络单元总结

规格实现

以翻译JML为主,对其中影响性能或不方便直接实现的方法做优化处理。

hw9

  • isCircle():用并查集实现
  • isLinked():用独立的静态类维护边表,再通过调用其查询方法实现

hw10

  • queryGroupValueSum():直接翻译JML是\(O(n^2)\)的,因此在加人、删人、加边时分别维护
  • queryGroupAgeVar():显然可以用\([(\sum x^2)-2E(x)(\sum x)+nE^2(x)]/ n\)实现

hw11

  • sendIndirectMessage():堆优化Dijkstra板子

基于JML的设计与测试

JML只描述方法执行前后的状态,而不关心过程。因此面向JML编程只需保证前后状态符合描述即可。

显然单元测试更符合JML本来的目的。相比于黑盒测试,单元测试解耦程度更高,测试颗粒度更低,更有利于bug定位。但单元测试也有问题,就是模拟软件真实运行时的上下文通常并不容易。相比之下,黑盒测试自由度更高,模拟真实场景更方便,但同样难以保证覆盖软件的全部运行状态。

我在作业中实际采用的做法是黑盒测试+对拍。整个过程分两阶段。第一阶段大家的代码都存在bug,通过对拍发现问题后分头修复,不断重复这个过程直到不出现明显bug。第二阶段是巨量测试,把电脑放寝室里一直跑,如果不出现新bug那么就有把握通过强测。

hw9

数据构造:主要卡并查集实现,数据生成器倾向于生成一两条长链

阶段二测试点总量:2k+

hw10

数据构造:纯随机生成,异常数量报表,主要用同学的生成器

阶段二测试点总量:1w+

hw11

数据构造:主要卡堆优化Dijkstra,生成10个接近团的稠密图,然后用少量边连接起来。同时使用了同学提供的其他指令的生成器

阶段二测试点总量:8k+

容器选用

遇事不决,上hashMap,准没错

由于存在id这种东西,所以很多容器可以直接设为Map<Integer, Integer>mp = new hashMap<>();的形式。

hw9

并查集fa[]数组用hashMap实现

边表用hashMap套hashMap实现

hw10

receivedMessages:由于需要支持头插,而且懒得用ArrayList实现栈,于是就用链表实现了

hw11

Dijkstra:显然要用priorityQueue做堆优化,还要用hashMap实现dis[]数组,同时还使用了hashSet维护了已计算完毕的点有哪些。

性能优化

维护嘛,平摊嘛,把\(O(n^2)\)的东西维护掉就好了

hw9

并查集:路经压缩+按秩合并

hw10

receivedMessage:链表实现,头插效率比ArryList高

QueryGroupValueSum:加人删人的时候\(O(n)\)维护sum,加边时\(O(1)\)维护sum。当然有些同学遍历邻接表也是可以的,因为总边数是\(O(n)\)的,而计算时每条边只会算两次。

hw11

最短路:堆优化Dijkstra板子。居然没看到有人用spfa,菊花图没用了,略失望

架构设计

hw9

独立的边表维护、查询静态类,可以算单例模式?

hw10

照抄JML,略

hw11

Dijkstra放在静态类中实现,简化了sendIndirectMessage()

啥,太短了???

你看这个类图,它又大又圆

hw9

hw9diagram

hw10

hw10diagram

hw11

hw11diagram

你看这个复杂度表,它又长又方

hw9

Method CogC ev(G) iv(G) v(G)
Ei.add(int,int,int) 3 2 3 4
Ei.be(int) 0 1 1 1
Ei.be(int,int) 2 2 2 3
Ei.lst(int) 1 1 1 2
Ei.v(int,int) 1 1 2 2
EpiE.EpiE(int) 0 1 1 1
EpiE.print() 0 1 1 1
ErE.ErE(int,int) 1 1 2 2
ErE.print() 0 1 1 1
Main.main(String[]) 0 1 1 1
Net.Net() 0 1 1 1
Net.addPerson(Person) 1 2 2 2
Net.addRelation(int,int,int) 3 4 3 4
Net.compareName(int,int) 2 3 2 3
Net.contains(int) 0 1 1 1
Net.find(int) 2 1 2 2
Net.getPerson(int) 0 1 1 1
Net.isCircle(int,int) 2 3 2 3
Net.mrg(int,int) 5 2 3 4
Net.queryBlockSum() 0 1 1 1
Net.queryNameRank(int) 4 2 2 4
Net.queryPeopleSum() 0 1 1 1
Net.queryValue(int,int) 3 4 3 4
PinfE.PinfE(int) 0 1 1 1
PinfE.print() 0 1 1 1
Psn.Psn(int,String,int) 0 1 1 1
Psn.compareTo(Person) 0 1 1 1
Psn.equals(Object) 1 2 1 2
Psn.getAge() 0 1 1 1
Psn.getId() 0 1 1 1
Psn.getName() 0 1 1 1
Psn.isLinked(Person) 1 1 2 2
Psn.queryValue(Person) 0 1 1 1
RnfE.RnfE(int,int) 1 1 2 2
RnfE.print() 0 1 1 1
Class OCavg OCmax WMC
Ei 2.2 4 11
EpiE 1 1 2
ErE 1.5 2 3
Main 1 1 1
Net 2.38 4 31
PinfE 1 1 2
Psn 1.12 2 9
RnfE 1.5 2 3

hw10

Method CogC ev(G) iv(G) v(G)
ntw.Grp.Grp(int) 0 1 1 1
ntw.Grp.addPerson(Person) 0 1 1 1
ntw.Grp.addRela(int,int,int) 2 1 2 3
ntw.Grp.delPerson(Person) 1 2 1 2
ntw.Grp.equals(Object) 1 1 2 2
ntw.Grp.getAgeMean() 1 1 2 2
ntw.Grp.getAgeVar() 1 1 2 2
ntw.Grp.getId() 0 1 1 1
ntw.Grp.getSize() 0 1 1 1
ntw.Grp.getValueSum() 0 1 1 1
ntw.Grp.hasPerson(Person) 0 1 1 1
ntw.Grp.peo() 0 1 1 1
ntw.Main.main(String[]) 0 1 1 1
ntw.Msg.Msg(int,int,Person,Group) 0 1 1 1
ntw.Msg.Msg(int,int,Person,Person) 0 1 1 1
ntw.Msg.equals(Object) 1 1 2 2
ntw.Msg.getGroup() 0 1 1 1
ntw.Msg.getId() 0 1 1 1
ntw.Msg.getPerson1() 0 1 1 1
ntw.Msg.getPerson2() 0 1 1 1
ntw.Msg.getSocialValue() 0 1 1 1
ntw.Msg.getType() 0 1 1 1
ntw.Msg.toString() 0 1 1 1
ntw.Net.addGroup(Group) 1 2 2 2
ntw.Net.addMessage(Message) 3 3 4 4
ntw.Net.addPerson(Person) 1 2 2 2
ntw.Net.addRelation(int,int,int) 4 4 4 5
ntw.Net.addToGroup(int,int) 4 4 4 5
ntw.Net.cmpNm(int,int) 0 1 1 1
ntw.Net.compareName(int,int) 2 3 2 3
ntw.Net.contains(int) 0 1 1 1
ntw.Net.containsMessage(int) 0 1 1 1
ntw.Net.delFromGroup(int,int) 3 4 3 4
ntw.Net.find(int) 2 1 2 2
ntw.Net.getGroup(int) 0 1 1 1
ntw.Net.getMessage(int) 0 1 1 1
ntw.Net.getPerson(int) 0 1 1 1
ntw.Net.isCircle(int,int) 2 3 2 3
ntw.Net.mrg(int,int) 5 2 3 4
ntw.Net.queryBlockSum() 0 1 1 1
ntw.Net.queryGroupAgeMean(int) 1 2 1 2
ntw.Net.queryGroupAgeVar(int) 1 2 1 2
ntw.Net.queryGroupPeopleSum(int) 1 2 1 2
ntw.Net.queryGroupSum() 0 1 1 1
ntw.Net.queryGroupValueSum(int) 1 2 1 2
ntw.Net.queryNameRank(int) 1 2 1 2
ntw.Net.queryPeopleSum() 0 1 1 1
ntw.Net.queryReceivedMessages(int) 1 2 1 2
ntw.Net.querySocialValue(int) 1 2 1 2
ntw.Net.queryValue(int,int) 4 4 4 5
ntw.Net.sendMessage(int) 7 4 8 8
ntw.Psn.Psn(int,String,int) 0 1 1 1
ntw.Psn.addSocialValue(int) 0 1 1 1
ntw.Psn.compareTo(Person) 0 1 1 1
ntw.Psn.equals(Object) 1 1 2 2
ntw.Psn.getAge() 0 1 1 1
ntw.Psn.getId() 0 1 1 1
ntw.Psn.getMessages() 0 1 1 1
ntw.Psn.getName() 0 1 1 1
ntw.Psn.getReceivedMessages() 2 1 3 3
ntw.Psn.getSocialValue() 0 1 1 1
ntw.Psn.isLinked(Person) 1 1 2 2
ntw.Psn.queryValue(Person) 0 1 1 1
ntw.Psn.toString() 0 1 1 1
ntw.Re.add(int,int,int) 3 2 3 4
ntw.Re.be(int) 0 1 1 1
ntw.Re.be(int,int) 1 1 3 3
ntw.Re.lst(int) 1 1 1 2
ntw.Re.v(int,int) 1 1 2 2
Class OCavg OCmax WMC
ntw.Eegi 1 1 2
ntw.Eemi 1 1 2
ntw.Eepi 1 1 2
ntw.Eer 1.5 2 3
ntw.Eginf 1 1 2
ntw.Eminf 1 1 2
ntw.Epinf 1 1 2
ntw.Ernf 1.5 2 3
ntw.Grp 1.33 2 16
ntw.Main 1 1 1
ntw.Msg 1 1 10

hw11

Method CogC ev(G) iv(G) v(G)
ntw.Grp.Grp(int) 0 1 1 1
ntw.Grp.addPerson(Person) 0 1 1 1
ntw.Grp.addRela(int,int,int) 2 1 2 3
ntw.Grp.delPerson(Person) 1 2 1 2
ntw.Grp.equals(Object) 1 1 2 2
ntw.Grp.getAgeMean() 1 1 2 2
ntw.Grp.getAgeVar() 1 1 2 2
ntw.Grp.getId() 0 1 1 1
ntw.Grp.getSize() 0 1 1 1
ntw.Grp.getValueSum() 0 1 1 1
ntw.Grp.hasPerson(Person) 0 1 1 1
ntw.Grp.peo() 0 1 1 1
ntw.Main.main(String[]) 0 1 1 1
ntw.Msg.Msg(int,int,Person,Group) 0 1 1 1
ntw.Msg.Msg(int,int,Person,Person) 0 1 1 1
ntw.Msg.equals(Object) 1 1 2 2
ntw.Msg.getGroup() 0 1 1 1
ntw.Msg.getId() 0 1 1 1
ntw.Msg.getPerson1() 0 1 1 1
ntw.Msg.getPerson2() 0 1 1 1
ntw.Msg.getSocialValue() 0 1 1 1
ntw.Msg.getType() 0 1 1 1
ntw.Msg.toString() 0 1 1 1
ntw.MsgEM.MsgEM(int,int,Person,Group) 0 1 1 1
ntw.MsgEM.MsgEM(int,int,Person,Person) 0 1 1 1
ntw.MsgEM.equals(Object) 1 1 2 2
ntw.MsgEM.getEmojiId() 0 1 1 1
ntw.MsgEM.getGroup() 0 1 1 1
ntw.MsgEM.getId() 0 1 1 1
ntw.MsgEM.getPerson1() 0 1 1 1
ntw.MsgEM.getPerson2() 0 1 1 1
ntw.MsgEM.getSocialValue() 0 1 1 1
ntw.MsgEM.getType() 0 1 1 1
ntw.MsgEM.toString() 0 1 1 1
ntw.MsgNT.MsgNT(int,String,Person,Group) 0 1 1 1
ntw.MsgNT.MsgNT(int,String,Person,Person) 0 1 1 1
ntw.MsgNT.equals(Object) 1 1 2 2
ntw.MsgNT.getGroup() 0 1 1 1
ntw.MsgNT.getId() 0 1 1 1
ntw.MsgNT.getPerson1() 0 1 1 1
ntw.MsgNT.getPerson2() 0 1 1 1
ntw.MsgNT.getSocialValue() 0 1 1 1
ntw.MsgNT.getString() 0 1 1 1
ntw.MsgNT.getType() 0 1 1 1
ntw.MsgNT.toString() 0 1 1 1
ntw.MsgRE.MsgRE(int,int,Person,Group) 0 1 1 1
ntw.MsgRE.MsgRE(int,int,Person,Person) 0 1 1 1
ntw.MsgRE.equals(Object) 1 1 2 2
ntw.MsgRE.getGroup() 0 1 1 1
ntw.MsgRE.getId() 0 1 1 1
ntw.MsgRE.getMoney() 0 1 1 1
ntw.MsgRE.getPerson1() 0 1 1 1
ntw.MsgRE.getPerson2() 0 1 1 1
ntw.MsgRE.getSocialValue() 0 1 1 1
ntw.MsgRE.getType() 0 1 1 1
ntw.MsgRE.toString() 0 1 1 1
ntw.Net.addGroup(Group) 1 2 2 2
ntw.Net.addMessage(Message) 5 4 6 6
ntw.Net.addPerson(Person) 1 2 2 2
ntw.Net.addRelation(int,int,int) 4 4 4 5
ntw.Net.addToGroup(int,int) 4 4 4 5
ntw.Net.cmpNm(int,int) 0 1 1 1
ntw.Net.compareName(int,int) 2 3 2 3
ntw.Net.contains(int) 0 1 1 1
ntw.Net.containsEmojiId(int) 0 1 1 1
ntw.Net.containsMessage(int) 0 1 1 1
ntw.Net.delFromGroup(int,int) 3 4 3 4
ntw.Net.deleteColdEmoji(int) 1 1 2 2
ntw.Net.find(int) 2 1 2 2
ntw.Net.getGroup(int) 0 1 1 1
ntw.Net.getMessage(int) 0 1 1 1
ntw.Net.getPerson(int) 0 1 1 1
ntw.Net.isCircle(int,int) 2 3 2 3
ntw.Net.linked(int,int) 0 1 1 1
ntw.Net.mrg(int,int) 5 2 3 4
ntw.Net.queryBlockSum() 0 1 1 1
ntw.Net.queryGroupAgeMean(int) 1 2 1 2
ntw.Net.queryGroupAgeVar(int) 1 2 1 2
ntw.Net.queryGroupPeopleSum(int) 1 2 1 2
ntw.Net.queryGroupSum() 0 1 1 1
ntw.Net.queryGroupValueSum(int) 1 2 1 2
ntw.Net.queryMoney(int) 1 2 1 2
ntw.Net.queryNameRank(int) 1 2 1 2
ntw.Net.queryPeopleSum() 0 1 1 1
ntw.Net.queryPopularity(int) 1 2 1 2
ntw.Net.queryReceivedMessages(int) 1 2 1 2
ntw.Net.querySocialValue(int) 1 2 1 2
ntw.Net.queryValue(int,int) 4 4 4 5
ntw.Net.sendIndirectMessage(int) 3 3 2 4
ntw.Net.sendMessage(int) 10 4 10 10
ntw.Net.sendT1(Message) 2 1 3 3
ntw.Net.storeEmojiId(int) 1 2 1 2
ntw.Psn.Psn(int,String,int) 0 1 1 1
ntw.Psn.addMoney(int) 0 1 1 1
ntw.Psn.addSocialValue(int) 0 1 1 1
ntw.Psn.compareTo(Person) 0 1 1 1
ntw.Psn.equals(Object) 1 1 2 2
ntw.Psn.getAge() 0 1 1 1

你看这个代码,它朴实无华

hw9

并查集:路经压缩+按秩合并

private final Map<Integer, Integer> fa = new HashMap<>();
private final Map<Integer, Integer> frnk = new HashMap<>();
private int blk = 0;

private int find(int x) {
  return fa.get(x) == x ? x : fa.merge(x, find(fa.get(x)), (a, b) -> b);
}

private boolean mrg(int xx, int yy) {
  int x = find(xx);
  int y = find(yy);
  if (x == y) {
    return false;
  }
  if (frnk.get(x) < frnk.get(y)) {
    fa.merge(x, y, (a, b) -> b);
  } else {
    fa.merge(y, x, (a, b) -> b);
    if (frnk.get(x).equals(frnk.get(y))) {
      frnk.merge(x, 1, Integer::sum);
    }
  }
  --blk;
  return true;
}

hw10

维护边权和:加人、减人、加边时维护

public void addPerson(Person person) {
  peo.add(person.getId());
  sum += person.getAge();
  sum2 += person.getAge() * person.getAge();
  peo.forEach((p) -> sume += Re.v(p, person.getId()));
}

public void delPerson(Person person) {
  if (!peo.contains(person.getId())) {
    return;
  }
  sum -= person.getAge();
  sum2 -= person.getAge() * person.getAge();
  peo.remove(person.getId());
  peo.forEach((p) -> sume -= Re.v(p, person.getId()));
}

public void addRela(int a, int b, int v) {
  if (peo.contains(a) && peo.contains(b)) {
    sume += v;
  }
}

public int getValueSum() {
  return sume << 1;
}

hw11

堆优化Dijkstra:

private static class Nd implements Comparable<Nd> {
  private final int id;
  private final int dis;

  public Nd(int id, int dis) {
    this.id = id;
    this.dis = dis;
  }

  @Override
  public int compareTo(Nd o) {
    return Integer.compare(dis, o.dis);
  }

  public int i() {
    return id;
  }
}


public static int dij(int u, int v) {
  Queue<Nd> q = new PriorityQueue<>();
  Map<Integer, Integer> dis = new HashMap<>();
  Set<Integer> in = new HashSet<>();
  dis.put(u, 0);
  q.offer(new Nd(u, 0));
  while (!q.isEmpty()) {
    int s = q.poll().i();
    if (in.contains(s)) {
      continue;
    }
    in.add(s);
    Map<Integer, Integer> es = lst(s);
    int sval = dis.get(s);
    es.forEach((t, val) -> {
      int tval = sval + val;
      if (dis.getOrDefault(t, INF) > tval) {
        dis.put(t, tval);
        q.offer(new Nd(t, tval));
      }
    });
  }
  return dis.getOrDefault(v, INF);
}
posted @ 2021-05-28 15:28  fallqs  阅读(170)  评论(0编辑  收藏  举报