# OO第三单元总结

## 架构设计

### 1.Network类集合容器选择

private final HashMap<Person, Integer> people;
private final ArrayList<Group> groups;
private final List<Message> messages;
private final HashMap<Integer, Integer> emojis;
private final PriorityQueue<Edge> edges = new PriorityQueue<>();


edge为people之间的关系集合，通过新建edge类来存储信息，每一个relation对应一条边，PriorityQueue的排序按照关系的value从小到大的顺序排列。具体实现如下：

public class Edge implements Comparable<Edge> {
private Person startPerson;
private Person endPerson;
private int value;

public Edge(Person startPerson, Person endPerson, int value) {
this.startPerson = startPerson;
this.endPerson = endPerson;
this.value = value;
}

public int getValue() {
return value;
}

public Person getEndPerson() {
return endPerson;
}

public Person getStartPerson() {
return startPerson;
}

@Override
public int compareTo(Edge edge) {
return this.value - edge.value;
}
}


### 2.图算法实现及维护

#### Kruskal算法求最小生成树

hw10中的qlc指令需要求连通图的最小生成树。具体实现通过创建工具类CalQ来计算最终结果。在传入参数时创建新的PriorityQueue并将该person所在的连通分支内的所有边都加入到这个优先队列中，将其作为参数初始化工具类，通过并查集来优化Kruskal算法复杂度。CalQ工具类具体实现如下，通过getSum函数求出最终结果。

import com.oocourse.spec2.main.Person;

import java.util.HashMap;
import java.util.PriorityQueue;

public class CalQ {
private PriorityQueue<Edge> edges;
private HashMap<Person, Person> father = new HashMap<>();
private HashMap<Person, Integer> people;

public CalQ(HashMap<Person, Integer> people,  PriorityQueue<Edge> edges) {
this.people = people;
this.edges = edges;
}

public void getEdges(int id) {
for (Person person1 : people.keySet()) {
if (people.get(person1).equals(people.get(getPerson(id)))) {
father.put(person1, person1);
}
}
}

public int getSum() {
int sum = 0;
while (!edges.isEmpty()) {
Edge edge = edges.poll();
Person f1 = findFather(edge.getStartPerson(), father);
Person f2 = findFather(edge.getEndPerson(), father);
if (!f1.equals(f2)) {
sum += edge.getValue();
father.put(f1, f2);
}
}
return sum;
}

private Person findFather(Person person, HashMap<Person, Person> father) {
Person f = father.get(person);
if (!f.equals(person)) {
f = findFather(f, father);
}
father.put(person, f);
return f;
}

public Person getPerson(int id) {
for (Person person : people.keySet()) {
if (person.getId() == id) {
return person;
}
}
return null;
}
}


#### Dijkstra算法求最短路

hw11中的sim指令需要求带权图中两点之间最短加权路径，根据评论区中的思路实现了基于堆优化的Dijkstra算法。首先把距离数组dis中出发点s距离设置为0，其余点设置为一个超出数据范围的较大数，标记数组vis全部设置为0，把点s加入优先队列。之后每次从优先队列中弹出一个节点u，因优先队列的特性该节点权值最小，若u已经被标记，则不作操作，否则将对应标记数组的值设为1，取出它的距离值，遍历它的所有边，假设u与v相连，若v被标记过，不做操作，否则比较dis(u) + w(u, v)与dis(v)，若前者较小，则将dis(v)改为dis(u) + w(u, v)，并把v加入优先队列。该步骤停止条件为优先队列为空。

import com.oocourse.spec3.main.Person;

public class Node implements Comparable<Node> {
private Person person;
private int value;

public Node(Person person, int value) {
this.person = person;
this.value = value;
}

public int getValue() {
return value;
}

public void setValue(int value) {
this.value = value;
}

public Person getPerson() {
return person;
}

@Override
public int compareTo(Node node) {
return this.value - node.value;
}
}


import com.oocourse.spec3.main.Person;

import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;

public class CalSim {
private HashMap<Person, Integer> dis = new HashMap<>();
private HashMap<Person, Integer> flags = new HashMap<>();
private PriorityQueue<Node> nodes = new PriorityQueue<>();
private HashMap<Person, Integer> people;

public CalSim(HashMap<Person, Integer> people) {
this.people = people;
}

public void getNodes(Person p1) {
for (Map.Entry<Person, Integer> entry : people.entrySet()) {
if (!entry.getKey().equals(p1)) {
flags.put(entry.getKey(), 0);
dis.put(entry.getKey(), 15000);
} else {
Node node = new Node(entry.getKey(), 0);
dis.put(entry.getKey(), 0);
flags.put(entry.getKey(), 0);
}
}
}

public void countDis() {
while (!nodes.isEmpty()) {
Node node = nodes.poll();
if (flags.get(node.getPerson()) == 0) {
flags.put(node.getPerson(), 1);
for (Person p : people.keySet()) {
if (node.getPerson().isLinked(p) && flags.get(p) == 0) {
if (dis.get(node.getPerson()) + node.getPerson().queryValue(p)
< dis.get(p)) {
dis.put(p, dis.get(node.getPerson()) +
node.getPerson().queryValue(p));
Node node1 = new Node(p, dis.get(node.getPerson()) +
node.getPerson().queryValue(p));
}
}
}
}
}
}

public int getDis(Person p) {
return dis.get(p);
}
}


### 出现的性能问题

@Override
for (Person p : people) {
valueSum += person.queryValue(p) * 2;
}
}
ageSum += person.getAge();
}


@Override
public void delPerson(Person person) {
ageSum -= person.getAge();
for (Person p : people) {
valueSum -= person.queryValue(p) * 2;
}
}
people.remove(person);
}


### Network扩展

/*@ public normal_behavior
@          getMessage(id).getPerson1() != getMessage(id).getPerson2() &&
@          getMessage(id).getPerson2() instanceof Customer;
@ assignable messages;
@ assignable getMessage(id).getPerson1().socialValue;
@ assignable getMessage(id).getPerson2().messages, getMessage(id).getPerson2().socialValue;
@ ensures !containsMessage(id) && messages.length == \old(messages.length) - 1 &&
@         (\forall int i; 0 <= i && i < \old(messages.length) && \old(messages[i].getId()) != id;
@         (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
@ ensures \old(getMessage(id)).getPerson1().getSocialValue() ==
@         \old(getMessage(id).getPerson1().getSocialValue()) + \old(getMessage(id)).getSocialValue() &&
@         \old(getMessage(id)).getPerson2().getSocialValue() ==
@         \old(getMessage(id).getPerson2().getSocialValue()) + \old(getMessage(id)).getSocialValue();
@ ensures (\forall int i; 0 <= i && i < \old(getMessage(id).getPerson2().getMessages().size());
@          \old(getMessage(id)).getPerson2().getMessages().get(i+1) == \old(getMessage(id).getPerson2().getMessages().get(i)));
@ ensures \old(getMessage(id)).getPerson2().getMessages().get(0).equals(\old(getMessage(id)));
@ ensures \old(getMessage(id)).getPerson2().getMessages().size() == \old(getMessage(id).getPerson2().getMessages().size()) + 1;
@ also
@ public normal_behavior
@ requires containsMessage(id) && getMessage(id).getType() == 1 && && getMessage(id) instanceof Advertisement
@ 		 &&  getMessage(id).getGroup().hasPerson(getMessage(id).getPerson1()) &&
@ assignable people[*].socialValue, messages;
@ ensures !containsMessage(id) && messages.length == \old(messages.length) - 1 &&
@         (\forall int i; 0 <= i && i < \old(messages.length) && \old(messages[i].getId()) != id;
@         (\exists int j; 0 <= j && j < messages.length; messages[j].equals(\old(messages[i]))));
@ ensures (\forall Person p; \old(getMessage(id)).getGroup().hasPerson(p) && p instanceof Customer;
@         p.getSocialValue() == \old(p.getSocialValue()) + \old(getMessage(id)).getSocialValue());
@ ensures (\forall int i; 0 <= i && i < people.length && !\old(getMessage(id)).getGroup().hasPerson(people[i]) && people[i] instance of Customer;
@          \old(people[i].getSocialValue()) == people[i].getSocialValue());
@ also
@ public exceptional_behavior
@ 		!(getMessage(id).getPerson2() instanceof Customer);
@ 		containsMessage(id) && getMessage(id).getType() == 0 &&
@ 		getMessage(id).getPerson2() instanceof Customer;
@ containsMessage(id) && getMessage(id).getType() == 1 &&
@          !(getMessage(id).getGroup().hasPerson(getMessage(id).getPerson1())) &&
@*/


/*@ public normal_behavior
@ requires containsProduct(id);
@ ensures \result == (\sum int i; 0 <= i && i < people.length && people[i] instanceof Producer
@  && people[i].containsProduct(getProduct(id)); people[i].getProductSales());
@ also
@ public exceptional_behavior
@ signals (ProductIdNotFoundException e) !containsProduct(id);
@*/
public /*@ pure @*/ int queryProductSalesSum(int id) throws
ProductIdNotFoundException;


/*@ public normal_behavior
@ requires contains(id1) && getPerson(id1) instanceof Producer &&
@ 		getPerson(id1).containsProduct(getProduct(id2));
@ assignable getPerson(id1).productSum;
@ ensures getPerson(id2).getProductSum(productId) ==
@           \old(getProducer(id1).getProductSum(id2)) + 1;
@ also
@ public exceptional_behavior
@ signals (PersonIdNotFoundException e) !contains(id1);
@ signals (WrongPersonTypeException e) contains(id1) && !(getPerson(id1) instanceof Producer);
@ signals (WrongProductException e) contains(id1) && getPerson(id1) instanceof Producer &&
@ 		!getPerson(id1).containsProduct(getProduct(id2))
@*/
public void produceProduct(int id1, int id2) throws
PersonIdNotFoundException, WrongPersonTypeException, WrongProductException;


## 总结与心得体会

posted @ 2022-06-06 10:37  JcDt  阅读(19)  评论(1编辑  收藏  举报