# BUAA_OO 第三单元总结

## 一、架构设计

#### 容器选择

private HashMap<Integer, Person> people = new HashMap<>();private HashMap<Integer, Group> groups = new HashMap<>();private HashMap<Integer, Message> messages = new HashMap<>();private HashMap<Integer, Integer> emo = new HashMap<>();private HashMap<Person, Integer> acquaintance = new HashMap<>();private HashMap<Integer, Integer> value = new HashMap<>();

 private LinkedList<Message> messages = new LinkedList<>();

sendIndirectMessage函数中，为了更好应用dijkstra算法，我又用了优先队列 PriorityQueue来存储距离，用 HashSet来存储已经访问过的点。

private PriorityQueue<Distance> pq = new PriorityQueue<>();private HashSet<Integer> visit = new HashSet<>();

#### 时间复杂度较高方法的总结

MyNetwork类中的：

• boolean isCircle(int id1, int id2)

• int queryBlockSum()

• int queryLeastConnectionid):

• int sendIndirectMessage(int id)

MyNetwork类中的：

• int getAgeVar()

• int getValueSum()

##### 对应优化策略

private int find(int p) {    int tmp = p;    while (tmp != parent.get(tmp)) {        tmp = parent.get(tmp);    }    return tmp;} public void merge(int p, int q) {        int proot = find(p);        int qroot = find(q);        if (proot == qroot) {            return;        }        blockSum--;        if (rank.get(proot) < rank.get(qroot)) {            parent.put(proot, qroot);        } else if (rank.get(proot) > rank.get(qroot)) {            parent.put(qroot, proot);        } else {            parent.put(proot, qroot);            int tmp = rank.get(qroot);            rank.put(qroot, tmp + 1);        }    }

public /*@ pure @*/ int queryLeastConnection(int id) throws PersonIdNotFoundException {    if (!contains(id)) {        throw new MyPersonIdNotFoundException(id);    } else {        int sum = 0;        ArrayList<Edge> tmpEdges = new ArrayList<>();        HashSet<Integer> tmpSet = new HashSet<>();        for (int i = 0; i < edges.size(); i++) {            if (find(edges.get(i).getId1()) == find(id)) {                tmpEdges.add(edges.get(i));                tmpSet.add(edges.get(i).getId1());                tmpSet.add(edges.get(i).getId2());            }        }        for (Integer key : tmpSet) {            parent2.put(key, key);            rank2.put(key, 1);        }        Collections.sort(tmpEdges);        int j = 0;        for (int i = 0; i < tmpEdges.size(); i++) {            if (find2(tmpEdges.get(i).getId1()) != find2(tmpEdges.get(i).getId2())) {                merge2(tmpEdges.get(i).getId1(), tmpEdges.get(i).getId2());                sum += tmpEdges.get(i).getValue();                j++;            }            if (j == (tmpSet.size() - 1)) {                break;            }        }        return sum;    }}

private int dijkstra(Person person1, Person person2) {    pq.clear();    minDis.clear();    visit.clear();    minDis.put(person1.getId(), 0);    pq.add(new Distance(0, person1));    while (!pq.isEmpty()) {        Distance dis = pq.poll();        Person person = dis.getPerson();        int distance = dis.getDistance();        if (person.equals(person2)) {            return distance;        }        if (visit.contains(person.getId())) {            continue;        }        visit.add(person.getId());        HashMap<Person, Integer> acquaintance = ((MyPerson) person).getAcquaintance();        for (Person key : acquaintance.keySet()) {            if (minDis.get(key.getId()) == null) {                minDis.put(key.getId(), INF);            }            int oriDistance = minDis.get(key.getId());            if (oriDistance > distance + person.queryValue(key)) {                int newDistance = distance + person.queryValue(key);                minDis.put(key.getId(), newDistance);                pq.add(new Distance(newDistance, key));            }        }    }    return -1;}

## 二、测试数据准备

• 利用JML规格来准备测试数据：

我主要利用了JML规格中的requires语句和 signals语句来生成测试数据，例如下面的addGroup方法，我就会让生成的数据覆盖groups中有当前有加的group和没有当前有加的group两种情况。

/*@ public normal_behavior  @ requires !(\exists int i; 0 <= i && i < groups.length; groups[i].equals(group));  @ assignable groups;  @ ensures groups.length == \old(groups.length) + 1;  @ ensures (\forall int i; 0 <= i && i < \old(groups.length);  @          (\exists int j; 0 <= j && j < groups.length; groups[j] == (\old(groups[i]))));  @ ensures (\exists int i; 0 <= i && i < groups.length; groups[i] == group);  @ also  @ public exceptional_behavior  @ signals (EqualGroupIdException e) (\exists int i; 0 <= i && i < groups.length;  @                                     groups[i].equals(group));  @*/   public void addGroup(/*@ non_null @*/Group group) throws EqualGroupIdException;

• 防止公测部分发生bug，我采用了对自己的代码运用随机生成的测试数据进行测试，同时与小伙伴们进行对拍的方式。

• 对于互测部分的hack，我会对同房伙伴的代码运用随机生成的测试数据进行测试，看是否有正确性问题。此外我采用构造极端数据的方式，多次执行时间复杂度高的指令来卡TLE。

## 四、对NetWork进行扩展

• Person：吃瓜群众，不发广告，不买东西，不卖东西

public class Advertiser extends MyPerson;public class Producer extends MyPerson;public class Customer extends MyPerson;public class Advertisement extends Message public class Product extends Message

• 发送广告：

/*@ public normal_behavior  @ requires (\exists int i; 0 <= i && i < people.length; people[i].getId() == id && people[i] instanceof Advertiser && people[i].containsAdvertisement(advertisementId));  @ assignable people[*].messages       @ ensures (\forall int i; 0 <= i && i < people.length; (getPerson(id).isLinked(people[i])) ==> (people[i].messages.length == \old(people[i].messages.length) + 1 && people[i].messages[0] == \old(getPerson(id).getAdvertisement(advertisementId)) && (\forall int j; 1 <= j && j < people[i].messages.length; people[i].messages[j] == \old(people[i].messages[j - 1]))));  @ ensures (\forall int i; 0 <= i && i < people.length; !(getPerson(id).isLinked(people[i])) ==> (people[i].messages.length == \old(people[i].messages.length && (\forall int j; 0 <= j && j < people[i].messages.length; people[i].messages[j] == \old(people[i].messages[j]))));  @ also  @ public exceptional_behavior   @ signals (PersonIdNotFoundException e) (\forall int i; 0 <= i && i < people.length; people[i].getId() != id || (people[i].getId() == id && !people[i] instanceof Advertiser));  @ signals (AdvertisementIdNotFoundException e) (\exists int i; 0 <= i && i < people.length && people[i].getId() == id && people[i] instanceof Advertiser; !people[i].containsAdvertisement(advertisementId));  @*/public void sendAdvertisement(int id, int advertisementId) throws PersonIdNotFoundException, AdvertisementIdNotFoundException;
• 查询商品价格

/*@ public normal_behavior      @ requires containsProduct(id);      @ ensures \result == getProduct(id).getPrice();      @ also      @ public exceptional_behavior      @ signals (ProductIdNotFoundException e) !containsProduct(id);      @*/    public /*@ pure @*/ int queryProductPrice(int id) throws ProductIdNotFoundException;
• 增加商品

/* @ public normal_behavior@ assignable products@ requires !containsProduct(id);@ ensures products.length == \old(products.length) + 1;@ ensures containsProduct(id);@ ensures (\forall int i; 0 <= i && i < \old(products.length)             (\exists int j; 0 <= j && j < products.length; products[j] == \old(productList[i])));@ also@ public exceptional_behavior@ signals (EqualProductIdException e) containsProduct(id);  public void addProduct(Product product) throws EqualProductIdException;

## 五、学习体会

posted @ 2022-06-06 11:30  GOOD__BOY  阅读(184)  评论(2编辑  收藏  举报