Java 中的 Prim 算法实现
Prim's Algorithm Implementation in Java
我正在尝试在 Java 中使用我的图形 HashMap + LinkedList 和 class 包含连接顶点和权重的边来实现 Prim 算法:
adjacencyList = new HashMap<T, LinkedList<Edge<T>>>();
我的想法是,从给定的顶点开始:
1)将所有顶点保存到一个 LinkedList 中,这样我就可以在每次访问它们时删除它们
2) 将路径保存到另一个 LinkedList 中,这样我就可以得到最终的 MST
3) 使用 PriorityQueue 查找 MIN weight
最后我需要MST、边数和总重量。
我对如何 return MST 感到很困惑,而且我的代码中几乎没有错误,我不知道如何修复它们!
首先我得到这个错误:
Prim.java:21: error: no suitable method found for addAll(LinkedList<Edge<T>>)
unvisited.addAll(graph.getVertices());
^
method Collection.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
method List.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
method AbstractCollection.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
method LinkedList.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
where T is a type-variable: T extends Comparable<T> declared in class Prim
看来问题出在我的 getVertices() 方法(return 图中的所有顶点),因为它 return 是 Set<T>
;我尝试使用 addAll 将所有内容放入一个 LinkedList 中,并得到 as return 这个 LinkedList 但它给了我同样的错误。我做错了什么?
public class Graph<T extends Comparable<T>> {
.
.
public Set<T> getVertices() {
if (adjacencyList.isEmpty()) {
System.out.println("Error message.\n");
return null;
} else
return adjacencyList.keySet();
}
}
第二个错误是:
Prim.java:28: error: incompatible types: T cannot be converted to Edge<T>
for (Edge<T> edge : graph.getAdjacentVertices(source)) {
^
where T is a type-variable:
T extends Comparable<T> declared in class Prim
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
我可以通过将 Edge<T>
转换为 source
来修复它,但我认为它根本没有任何意义,因为我的想法是我给出一个可以包含任何类型的顶点,而不是只有边。
普里姆的:
public class Prim<T extends Comparable<T>> {
public <SHOULD I RETURN graph ?> minimumSpanningTree(Graph<Edge<T>> graph, T vertex) {
//ArgumentException
double weight = 0;
T source = vertex;
LinkedList<T> vertexSet = new LinkedList<>();
LinkedList<Edge<T>> path = new LinkedList<>();
vertexSet.addAll(graph.getVertices()); //unvisited ERROR HERE
vertexSet.remove(source);
double numberOfVertices = graph.getVertices().size();
PriorityQueue<Edge<T>> priorityQueue = new PriorityQueue<>();
while (!vertexSet.isEmpty()) {
for (Edge<T> edge : graph.getAdjacentVertices(source)) {//ERROR
if (vertexSet.contains(edge.getDestination()))
priorityQueue.insert(edge);
}
Edge<T> minWeight = priorityQueue.extractMin();
weight += minWeight.getWeight();
path.add(HERE I SHOULD PUT MST PATH BUT I DON'T KNOW HOW!!);
source = minWeight.getDestination();
vertexSet.remove(source);
}
return <graph??>;
}
}
正如我之前所说,我不知道我是否应该 return 一个图作为 MST(也许我作为输入给出的那个删除了最昂贵的边)或名为 path 的 LinkedList 保存路径重量最低。
我也不知道如何找到 MST 中的边数;我应该为每个顶点(我的 HashMap 的 keySet)找到 LinkedList 的大小(这是它的值)并将它们全部相加吗?
编辑:getAdjacentVertices 方法
public LinkedList<T> getAdjacentVertices(T vertex) {
if (adjacencyList.isEmpty() || adjacencyList.containsKey(vertex) == false) {
System.out.println("Error msg.\n");
return null;
} else {
LinkedList<T> allAdjacents = new LinkedList<>();
for (Edge<T> edge : adjacencyList.get(vertex)) {
allAdjacents.add(edge.getDestination());
}
return allAdjacents;
}
}
1) 我想错误不在 getVertices()
中,但事实上您的 Graph
在 Edge<T>
而不是 T
上被定义为通用。 Graph<T>
实例化为 Graph<Edge<T1>>
,因此 Set<T>
作为 return 值实例化为 Set<Edge<T1>>
.
我建议您将 Graph
定义为 Graph<Edge<T>>
,并从那里重构图的逻辑,或者将 IEdge<T>
定义为 Edge<T>
的超接口并将图重新定义为 Graph<? extends IEdge<T>>
.
例如(蒙上眼睛):
public class Graph<T> {
Map<T, Edge<T>> adjacencyList;
public Set<T> getVertices() {
if (adjacencyList.isEmpty()) {
System.out.println("Error message.\n");
return null;
} else {
return adjacencyList.keySet();
}
}
}
Graph<Point> p;
List<Point> points = new LinkedList<>();
points.addAll(p.getVertices());
2) 1 的变体。在这种情况下,您正在 returning a List<T>
但由于您正在骑自行车:
for (Edge<T> edge : graph.getAdjacentVertices(source))
getAdjacentVertices
的 return 值应该是 Enumerable<Edge<T>>
,而您提供的是 Enumerable<T>
。您可能希望在 getAdjacentVertices
实施中 return 类似这样的内容:
LinkedList<Edge<T>> allAdjacents = new LinkedList<>();
for (Edge<T> edge : adjacencyList.get(vertex)) {
allAdjacents.add(edge);
}
return allAdjacents;
我正在尝试在 Java 中使用我的图形 HashMap + LinkedList 和 class 包含连接顶点和权重的边来实现 Prim 算法:
adjacencyList = new HashMap<T, LinkedList<Edge<T>>>();
我的想法是,从给定的顶点开始: 1)将所有顶点保存到一个 LinkedList 中,这样我就可以在每次访问它们时删除它们 2) 将路径保存到另一个 LinkedList 中,这样我就可以得到最终的 MST 3) 使用 PriorityQueue 查找 MIN weight
最后我需要MST、边数和总重量。 我对如何 return MST 感到很困惑,而且我的代码中几乎没有错误,我不知道如何修复它们!
首先我得到这个错误:
Prim.java:21: error: no suitable method found for addAll(LinkedList<Edge<T>>)
unvisited.addAll(graph.getVertices());
^
method Collection.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
method List.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
method AbstractCollection.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
method LinkedList.addAll(Collection<? extends T>) is not applicable
(argument mismatch; LinkedList<Edge<T>> cannot be converted to Collection<? extends T>)
where T is a type-variable: T extends Comparable<T> declared in class Prim
看来问题出在我的 getVertices() 方法(return 图中的所有顶点),因为它 return 是 Set<T>
;我尝试使用 addAll 将所有内容放入一个 LinkedList 中,并得到 as return 这个 LinkedList 但它给了我同样的错误。我做错了什么?
public class Graph<T extends Comparable<T>> {
.
.
public Set<T> getVertices() {
if (adjacencyList.isEmpty()) {
System.out.println("Error message.\n");
return null;
} else
return adjacencyList.keySet();
}
}
第二个错误是:
Prim.java:28: error: incompatible types: T cannot be converted to Edge<T>
for (Edge<T> edge : graph.getAdjacentVertices(source)) {
^
where T is a type-variable:
T extends Comparable<T> declared in class Prim
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
我可以通过将 Edge<T>
转换为 source
来修复它,但我认为它根本没有任何意义,因为我的想法是我给出一个可以包含任何类型的顶点,而不是只有边。
普里姆的:
public class Prim<T extends Comparable<T>> {
public <SHOULD I RETURN graph ?> minimumSpanningTree(Graph<Edge<T>> graph, T vertex) {
//ArgumentException
double weight = 0;
T source = vertex;
LinkedList<T> vertexSet = new LinkedList<>();
LinkedList<Edge<T>> path = new LinkedList<>();
vertexSet.addAll(graph.getVertices()); //unvisited ERROR HERE
vertexSet.remove(source);
double numberOfVertices = graph.getVertices().size();
PriorityQueue<Edge<T>> priorityQueue = new PriorityQueue<>();
while (!vertexSet.isEmpty()) {
for (Edge<T> edge : graph.getAdjacentVertices(source)) {//ERROR
if (vertexSet.contains(edge.getDestination()))
priorityQueue.insert(edge);
}
Edge<T> minWeight = priorityQueue.extractMin();
weight += minWeight.getWeight();
path.add(HERE I SHOULD PUT MST PATH BUT I DON'T KNOW HOW!!);
source = minWeight.getDestination();
vertexSet.remove(source);
}
return <graph??>;
}
}
正如我之前所说,我不知道我是否应该 return 一个图作为 MST(也许我作为输入给出的那个删除了最昂贵的边)或名为 path 的 LinkedList 保存路径重量最低。 我也不知道如何找到 MST 中的边数;我应该为每个顶点(我的 HashMap 的 keySet)找到 LinkedList 的大小(这是它的值)并将它们全部相加吗?
编辑:getAdjacentVertices 方法
public LinkedList<T> getAdjacentVertices(T vertex) {
if (adjacencyList.isEmpty() || adjacencyList.containsKey(vertex) == false) {
System.out.println("Error msg.\n");
return null;
} else {
LinkedList<T> allAdjacents = new LinkedList<>();
for (Edge<T> edge : adjacencyList.get(vertex)) {
allAdjacents.add(edge.getDestination());
}
return allAdjacents;
}
}
1) 我想错误不在 getVertices()
中,但事实上您的 Graph
在 Edge<T>
而不是 T
上被定义为通用。 Graph<T>
实例化为 Graph<Edge<T1>>
,因此 Set<T>
作为 return 值实例化为 Set<Edge<T1>>
.
我建议您将 Graph
定义为 Graph<Edge<T>>
,并从那里重构图的逻辑,或者将 IEdge<T>
定义为 Edge<T>
的超接口并将图重新定义为 Graph<? extends IEdge<T>>
.
例如(蒙上眼睛):
public class Graph<T> {
Map<T, Edge<T>> adjacencyList;
public Set<T> getVertices() {
if (adjacencyList.isEmpty()) {
System.out.println("Error message.\n");
return null;
} else {
return adjacencyList.keySet();
}
}
}
Graph<Point> p;
List<Point> points = new LinkedList<>();
points.addAll(p.getVertices());
2) 1 的变体。在这种情况下,您正在 returning a List<T>
但由于您正在骑自行车:
for (Edge<T> edge : graph.getAdjacentVertices(source))
getAdjacentVertices
的 return 值应该是 Enumerable<Edge<T>>
,而您提供的是 Enumerable<T>
。您可能希望在 getAdjacentVertices
实施中 return 类似这样的内容:
LinkedList<Edge<T>> allAdjacents = new LinkedList<>();
for (Edge<T> edge : adjacencyList.get(vertex)) {
allAdjacents.add(edge);
}
return allAdjacents;