我可以用什么方法来表示Java中的加权有向图?

时间:2018-12-05 18:11:34

标签: java graph

我需要一种通过邻接来遍历图并返回路径总权重的方法。我不确定如何在方法“ public double getPathWeight(List path)”中增加权重。另外,可能我感觉我的公共void addEdge方法可能包含一些错误,因此,如果我也能对该方法获取一些指针,那将极大地帮助我完成图形。我的图形是根据通用VertexType参数编写的。而且我正在处理邻接表数据结构。

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

    }

}

2 个答案:

答案 0 :(得分:1)

在没有给您答案的情况下,让我概述一种方法。假设我们有以下数据:

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

因此A已连接到CDC已连接到D。一个简单的DAG。

让我们计算路径A -> C -> D的成本。

首先,我们计算顶点A -> C的成本。我们需要从外部地图中获得A,这给了我们{C -> 10, D -> 100}。接下来,我们需要获得顶点的末端,因此我们从内部C-Map获得10

所以A -> C = 10

首先,我们计算顶点C -> D的成本。我们需要从外部地图中获得C,这给了我们{C -> {D -> 10}}。接下来,我们需要获得顶点的末端,因此我们从内部D-Map获得10

所以C -> D = 10

总费用:20


用于此的算法是什么样的?用伪代码:

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

我们遍历path直到结束之前的一项。然后,我们从adjacency获取起始顶点,并从inner获取终止顶点。这给了我们这一优势的成本。我们将其加到总计中。

然后我们沿着path移动一个-上一个结束边变为下一个开始边。

我们一直循环到path结束之前的一个,因为我们总是在“向前看”一项;即最后一个边不能成为起始边,因为没有结束边。

答案 1 :(得分:1)

为简单起见,我希望您考虑一些事项:

  • 为什么要在Set方法中引入addEdge?您可以完成没有边缘的添加任务吗?

  • 如何计算路径的权重? 考虑简单地迭代getPathWeight参数中给出的节点/顶点并在adjacency中进行查找。

我认为这很容易,您只需要知道如何获取介于两个给定顶点之间的边缘权重(但首先,您需要从adjacency中检查是否该边缘确实存在,或者path给出的列表不正确,在这种情况下可能会引发异常)。

实际的代码看起来像这样,但是我建议您先自己思考,然后再尝试编写代码,然后再继续阅读。 :)(我认为,如果您可以确定图的数据结构-Map<VertexType, Map<VertexType, Double>>,并且感觉足够好,那么您可以轻松地用正确的代码填充getPathWeight方法自己)

您可以使用这种简单的addEdge实现:

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

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;
}