Reputation: 9149
I'm trying to create a simple directed graph data structure backed by a Hashtable
which looks like this:
private Hashtable<V, List<Edge<V, K>>> adjacencyTable;
Where V
is the vertex type and K
is the data stored in an edge. The Edge
class simply stores a reference to the two vertices it lies between as well as some object of type K
. So...
1 | (1, 2, data_1), (1, 3, data_2)
2 | (2, 3, data_3)
3 | (3, 1, data_4)
So in order to do something simple like removeVertex(3)
, I have to loop through all the edges for each vertex, check if their to
property is equal to the vertex I'm trying to remove, and then delete them. Is there a better way to implement something like this?
Upvotes: 0
Views: 856
Reputation: 46960
Yes you're right this is an awkward choice. Consider instead using
Map<V, Map<V, K>> adjacencies = new Hashmap<>();
The nodes adjacent to p
are adjacencies.get(p).keyset()
, and the data for edge p->q
is adjacencies.get(p).get(q)
.
Removing vertex r
is bound to be a tricky operation because you need to remove the both in- and out-edges of r
. However you can make it quick by maintaining a parallel "reverse adjacency" list.
Map<V, Set<V>> reverseAdjacencies = new Hashmap<>();
Every time you add an adjacency p->q
with something like:
Map<V, K> edgesFromP = adjacencies.get();
if (edgesFromP == null) {
edgesFromP = new HashMap<>();
adjacencies.put(p, edgesFromP);
}
edgesFromP.put(q, nodeData);
the reverse map needs to be updated, too, with something like
Set<V> edgesToQ = reverseAdjacencies.get(q);
if (edgesToQ == null) {
edgesToQ = new HashSet<>();
reverseAdjacencies.put(q, edgesToQ);
}
edgesToQ.add(p);
Now to delete node 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);
I've left out details like null checks.
Upvotes: 2