BUAA-OO-U3-Summary

BUAA-OO-U3-Summary

1 问题描述

本单元的主要任务是根据JML描述来实现一个人际关系管理网络。

该网络有三个层面,person,group以及network。首先,network是最顶层的结构,所有的人都属于这一个网络,主要处理人与人之间的关系网络;group就像是群聊,可以容纳部分(或全部)人,但group之间并没有互斥性,就像是同一个人可以加入不同的群聊一样,主要处理年龄、消息和“社交能量”的统计;person就是一个个体,存储了这个人与哪些人有关以及收到的消息等。

2 总体架构

本单元在架构上的自主性不强,主要通过完成JML的描述来进行。其中,三次作业对JML描述的实现上有以下几个重点:

作业 问题 解决
hw9 qci(两个人是否在同一个连通块中)与qbs(查新连通块的数量) 新建一个union类,通过路径压缩 + 按秩合并优化的并查集解决
hw10 qlc(查询个人所在的连通块的最小生成树) 利用kruskal算法计算单次答案,利用并查集父节点保存和更新答案
hw11 sim(求连通块中两点间的最短路径) 利用Dijkstra算法计算答案

具体实现如下:

 //并查集
public class MyUnion {
    private final HashMap<Integer, Integer> fa;
    private final HashMap<Integer, Integer> size;

    public MyUnion() {
        fa = new HashMap<>();
        size = new HashMap<>();
    }

    public void add(int id) {
        fa.put(id, id);
        size.put(id, 1);
    }

    public int getfa(int id) {
        if (fa.get(id) == id) {
            return id;
        }
        int father = getfa(fa.get(id));
        fa.put(id, father);
        return father;
    }

    public void merge(int id1, int id2) {
        int fa1 = getfa(id1);
        int fa2 = getfa(id2);
        if (fa1 == fa2) {
            return;
        }
        if (size.get(fa1) > size.get(fa2)) {
            int fa = fa1;
            fa1 = fa2;
            fa2 = fa;
        }
        fa.put(fa1, fa2);
        size.merge(fa2, size.get(fa1), Integer::sum);
    }
}
    //qlc update (kruskal)
    private void update(int id) {
        MyUnion u = new MyUnion();
        int sum = 0;
        int cnt = 0;
        PriorityQueue<Integer> edges =
                new PriorityQueue<>(Comparator.comparingInt(this::edgeValue));
        for (MyPerson p : people.values()) {
            if (union.getfa(p.getId()) == union.getfa(id)) {
                u.add(p.getId());
                ++cnt;
            }
        }
        for (int i = 0; i < edgeCnt; i++) {
            int x = edgeX.get(i);
            if (union.getfa(x) == union.getfa(id)) {
                edges.add(i);
            }
        }
        while (!edges.isEmpty() && cnt > 1) {
            int i = edges.poll();
            int x = edgeX.get(i);
            int y = edgeY.get(i);
            if (union.getfa(x) == union.getfa(id) &&
                    union.getfa(y) == union.getfa(id) &&
                    u.getfa(x) != u.getfa(y)) {
                u.merge(x, y);
                sum += edgeValue(i);
                --cnt;
            }
        }
        minConnection.put(union.getfa(id), sum);
        updated.put(union.getfa(id), true);
    }
    //dijkstra
    private int getDis(int st, int ed) {
        HashMap<Integer, Integer> dis = new HashMap<>();
        PriorityQueue<MyPoint> queue = new PriorityQueue<>();
        queue.add(new MyPoint(st, 0));
        dis.put(st, 0);
        while (!queue.isEmpty()) {
            MyPoint point = queue.poll();
            if (point.getDis() != dis.get(point.getId())) {
                continue;
            }
            MyPerson x = people.get(point.getId());
            for (Person p : x.getAcquaintance().values()) {
                if (dis.get(p.getId()) == null ||
                        dis.get(p.getId()) > point.getDis() + x.queryValue(p)) {
                    dis.put(p.getId(), point.getDis() + x.queryValue(p));
                    queue.add(new MyPoint(p.getId(), point.getDis() + x.queryValue(p)));
                }
            }
        }
        return dis.get(ed);
    }

3 互测总结

本次实验在互测中的限制较大,难以通过性能进行hack,因此hack成功率不高;

同时,作为一个被公开的“1111”,受到了房间中多人X多次的hack,总的来说是一次惨痛的失败经历。

4 个人总结

本次实验相对来说是一次比较简单的实验,由于JML描述对操作的接口和影响进行了限制,在完成单个函数的过程中几乎不需要考虑过多,一般通过查找新增功能涉及的函数->设计新功能->依次实现各个函数三个步骤即可,也令我感受到了规格化设计对实现的巨大简化效果。

posted @ 2022-06-05 17:35  Fixed丨  阅读(17)  评论(0编辑  收藏  举报