Jonathan Mensi
Jonathan Mensi

Reputation: 33

What way I can represent a weighted, directed graph in Java?

I need a method that would traverse the graph by operating on adjacency, returning the total weight of path. I'm not sure how to go about adding weight in the method "public double getPathWeight(List path)". Also, possibly I have the feeling that my public void addEdge method might contain some errors, so if I could get some pointers on that method as well, it would help me out tremendously completing my graph. My graph is written in terms of a generic VertexType parameter. And I am operating on an adjacency list data structure.

import java.util.HashMap;
import java.util.HashSet;
import java.util.TreeMap;
import java.util.Map;
import java.util.Set;
import java.util.List;

public class Graph<VertexType> {
private Map<VertexType, TreeMap<VertexType, Double>> adjacency;

public Graph()
{
    adjacency = new java.util.HashMap<>();
}

public void addEdge(VertexType v1, VertexType v2, double weight)
{
    Set <VertexType> set = new HashSet<VertexType>(); 

    if(adjacency.get(v1)!=null)
    {
        set = (Set<VertexType>) adjacency.get(v1); 
        set.add(v2); 
        adjacency.put(v1,(TreeMap<VertexType, Double>) set); 
    }
    else //adds edge if adjacency is null
    {
        set.add(v2); 
        adjacency.put(v1,(TreeMap<VertexType, Double>) set); 
    }
}


public Set<VertexType> getVertices()
{
    return adjacency.keySet();
}

public void dumpGraph()
{
    for (Map.Entry<VertexType,TreeMap<VertexType,Double>> entry :
             adjacency.entrySet())
    {
        System.out.println(entry.getKey() + " -> " + 
entry.getValue());
    }
}


public double getPathWeight(List<VertexType> path) throws 
GraphPathException
{

       //need help with this method

    }

}

Upvotes: 3

Views: 1760

Answers (2)

Lavish Kothari
Lavish Kothari

Reputation: 2331

To keep it simple, I'd like you to ponder upon somethings:

  • Why are you introducing Set in your addEdge method? Can you do the task of adding the edge without it?

  • How to calculate the weight of the path? Think of simply iterating over the nodes/vertices given in the argument of getPathWeight and have lookups in your adjacency.

I think it is pretty easy, you just need to know how to get weight of edge that is between 2 given vertices (But first you need to check from your adjacency that whether that edge really exists, or the list given by path is not correct, may be throw an exception in that case).

The actual code will look something like this, but I'd suggest you to first think by yourself and try to write code before reading further. :) (I think if you can decide the data-structure for the Graph - which is Map<VertexType, Map<VertexType, Double>>, and I feel it is good enough, then you can easily fill up the getPathWeight method with correct code all by yourself)

You can have this type of simple addEdge implementation:

public void addEdge(VertexType v1, VertexType v2, double weight) {
    adjacency.computeIfAbsent(v1, v -> new HashMap<>()).put(v2,weight);
}

A simple implementation of getPathWeight:

public double getPathWeight(List<VertexType> path) throws GraphPathException {
    VertexType previousVertex = path.get(0);

    double resultWeight = 0.0;
    for (int i = 1; i < path.size(); i++) {
        VertexType currentVertex = path.get(i);
        Map<VertexType, Double> adjacencyForPreviousVertex = adjacency.get(previousVertex);
        if (adjacencyForPreviousVertex == null) {
            throw new GraphPathException("Vertex " + previousVertex + " don't exist in graph");
        }
        Double currentEdgeWeight = adjacencyForPreviousVertex.get(currentVertex);
        if (currentEdgeWeight == null) {
            throw new GraphPathException(currentVertex + "Vertex don't exist as an adjacent Vertex of " + previousVertex);
        }
        resultWeight += currentEdgeWeight;
        previousVertex = currentVertex;
    }
    return resultWeight;
}

Upvotes: 1

Boris the Spider
Boris the Spider

Reputation: 61198

Without giving you the answer, let me outline an approach. Lets assume we have the following data:

{A -> {C -> 10, D -> 100}}
{C -> {D -> 10}}
{D -> {}}

So A is connected to C & D, C is connected to D. A farily simple DAG.

Lets calculate the cost of a path A -> C -> D.

First we calculate the cost of the vertex A -> C. We need to get A from the outer map, this gives us {C -> 10, D -> 100}. Next we need to get the end of the vertex, so we get C from the inner Map - 10.

So A -> C = 10.

First we calculate the cost of the vertex C -> D. We need to get C from the outer map, this gives us {C -> {D -> 10}}. Next we need to get the end of the vertex, so we get D from the inner Map - 10.

So C -> D = 10.

Total Cost: 20


What does an algorithm for this look like? In pseudocode:

double weight = 0;
for (int i = 0; i < path.size() - 1; ++i) {
    Map<> inner = adjacency[path[i]]
    weight += inner[path[i + 1]]
}

We loop through the path until one item before the end. We then get the start vertex from the adjacency and get the end vertex from the inner. This gives us the cost of that edge. We add that that to total.

We then move one along the path - previous end edge becomes the next start edge.

We loop until one before the end of the path as we're always "looking ahead" one item; i.e. the last edge cannot become a start edge as there is no end edge.

Upvotes: 1

Related Questions