简体   繁体   English

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

[英]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)". 我不知道如何在方法“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. 另外,我可能觉得我的public void addEdge方法可能包含一些错误,所以如果我能得到一些关于该方法的指针,它将帮助我完成我的图表。 My graph is written in terms of a generic VertexType parameter. 我的图表是根据通用VertexType参数编写的。 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

    }

}

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连接到CDC连接到D A farily simple DAG. 一个简单的DAG。

Lets calculate the cost of a path A -> C -> D . 让我们计算路径A -> C -> D的成本。

First we calculate the cost of the vertex A -> C . 首先我们计算顶点A -> C的成本。 We need to get A from the outer map, this gives us {C -> 10, D -> 100} . 我们需要从外部地图获得A ,这给了我们{C -> 10, D -> 100} Next we need to get the end of the vertex, so we get C from the inner Map - 10 . 接下来我们需要得到顶点的末尾,所以我们从内部Map - 10得到C

So A -> C = 10 . 所以A -> C = 10

First we calculate the cost of the vertex C -> D . 首先我们计算顶点C -> D的成本。 We need to get C from the outer map, this gives us {C -> {D -> 10}} . 我们需要从外部地图中获取C ,这给了我们{C -> {D -> 10}} Next we need to get the end of the vertex, so we get D from the inner Map - 10 . 接下来我们需要得到顶点的末尾,所以我们从内部Map - 10得到D

So C -> D = 10 . 所以C -> D = 10

Total Cost: 20 总费用: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. 我们遍历path直到结束前的一个项目。 We then get the start vertex from the adjacency and get the end vertex from the inner . 然后我们从adjacency获取起始顶点并从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. 然后我们沿path移动一个 - 前一个边缘成为下一个起始边缘。

We loop until one before the end of the path as we're always "looking ahead" one item; 我们循环到path结束前的一个,因为我们总是“向前看”一个项目; ie the last edge cannot become a start edge as there is no end edge. 即最后一条边不能成为起始边,因为没有结束边。

To keep it simple, I'd like you to ponder upon somethings: 为了简单起见,我希望你能够思考一些事情:

  • Why are you introducing Set in your addEdge method? 为什么要在addEdge方法中引入Set 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 . 想象一下,只需迭代getPathWeight参数中给出的节点/顶点,并在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). 我认为这很简单,你只需要知道如何获得2个给定顶点之间的边缘权重 (但首先你需要检查你的adjacency是否真的存在这个边缘,或者path给出的列表是不正确的,在这种情况下可能会抛出异常)。

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) :)(我想如果你可以决定Graph的数据结构 - Map<VertexType, Map<VertexType, Double>> ,我觉得它已经足够好了,那么你可以很容易地用正确的方法填充getPathWeight方法代码全部由你自己)

You can have this type of simple addEdge implementation: 您可以使用此类简单的addEdge实现:

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

A simple implementation of getPathWeight : 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM