[英]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
连接到C
& D
, C
连接到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.