我正在尝试创建一个由Hashtable
支持的简单有向图数据结构,如下所示:
private Hashtable<V, List<Edge<V, K>>> adjacencyTable;
其中V
是顶点类型,K
是存储在边缘的数据。 Edge
类只存储它所在的两个顶点的引用以及类型K
的某个对象。所以......
1 | (1, 2, data_1), (1, 3, data_2)
2 | (2, 3, data_3)
3 | (3, 1, data_4)
所以为了做一些简单的事情,比如removeVertex(3)
,我必须遍历每个顶点的所有边,检查它们的to
属性是否等于我想要删除的顶点,然后删除它们。有没有更好的方法来实现这样的东西?
答案 0 :(得分:2)
是的,你是对的,这是一个尴尬的选择。请改为使用
Map<V, Map<V, K>> adjacencies = new Hashmap<>();
与p
相邻的节点为adjacencies.get(p).keyset()
,边p->q
的数据为adjacencies.get(p).get(q)
。
删除顶点r
一定是一项棘手的操作,因为你需要删除r
的入边和边出边。但是,您可以通过维护并行的“反向邻接”列表来快速完成。
Map<V, Set<V>> reverseAdjacencies = new Hashmap<>();
每次使用以下内容添加邻接p->q
时
Map<V, K> edgesFromP = adjacencies.get();
if (edgesFromP == null) {
edgesFromP = new HashMap<>();
adjacencies.put(p, edgesFromP);
}
edgesFromP.put(q, nodeData);
反向地图也需要更新,例如
Set<V> edgesToQ = reverseAdjacencies.get(q);
if (edgesToQ == null) {
edgesToQ = new HashSet<>();
reverseAdjacencies.put(q, edgesToQ);
}
edgesToQ.add(p);
现在删除节点r
,
// Remove the in-edges to r.
for (V p : reverseAdjacencies.remove(r)) {
adjacencies.get(p).remove(r);
}
// Remove r and all its out-edges
adjacencies.remove(r);
我遗漏了空检查等细节。