- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我无法让我的代码遵循第 635 页中 CLRS 的最小生成树 (MST) 示例。我还从字面上实现了 CLRS 的 MST-Prim 伪代码,即
所以我实际上有两个问题。第一个是在将节点 b
添加到 MST 之后,我的代码选择作为 PriorityQueue 节点 h
中的下一个元素,而不是节点 c
。我不确定 Java 的实现如何在关系的情况下选择元素,所以如果我能做些什么请告知。为了暂时规避这个问题,我修改了边 a-h
的权重为 9。
然后一切都正常运行,直到它在将 f
添加到 MST 之后选择节点 d
而不是 g
,我觉得这很奇怪,因为PriorityQueue 显然有 g
和 key=6
。
我的实现如下:
import java.util.LinkedList;
import java.util.PriorityQueue;
class Edge{
private Node source;
private Node destination;
private int weight;
public void setSource(Node source) {
this.source = source;
}
public void setDestination(Node destination) {
this.destination = destination;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getWeight() {
return this.weight;
}
public Node getSource() {
return this.source;
}
public Node getDestination() {
return this.destination;
}
}
class Node implements Comparable<Node>{
private String label;
private LinkedList<Edge> edges;
private int key;
private Node daddy;
Node() {
this.edges = new LinkedList();
}
public void setLabel(String label) {
this.label = label;
}
public void setKey(int key) {
this.key = key;
}
public void setDaddy(Node daddy) {
this.daddy = daddy;
}
public String getLabel() {
return this.label;
}
public int getKey() { return this.key; }
public LinkedList getEdges() {
return this.edges;
}
@Override
public int compareTo(Node o) {
if (this.getKey() > o.getKey()) {
return 1;
}
else if (this.getKey() < o.getKey()) {
return -1;
}
else {
return 0;
}
}
}
public class Graph {
private int numberOfNodes;
private Node[] weightedGraph;
public Graph(int graphV) {
this.numberOfNodes = graphV;
this.weightedGraph = new Node[this.numberOfNodes];
for (int i = 0; i < this.numberOfNodes; i++) {
this.weightedGraph[i] = new Node();
}
}
public void addEdge(String sourceLabel, String destinationLabel, int weight) {
Node sourceNode = null;
Node destinationNode = null;
for (Node node: this.weightedGraph) {
if (node.getLabel().contains(sourceLabel)) {
sourceNode = node;
}
if (node.getLabel().contains(destinationLabel)) {
destinationNode = node;
}
}
Edge e = new Edge();
e.setWeight(weight);
e.setSource(sourceNode);
e.setDestination(destinationNode);
sourceNode.getEdges().add(e);
}
public void minimumSpanningTree(String root) {
Node rootNode = null;
for (Node vertex: this.weightedGraph) {
vertex.setKey(Integer.MAX_VALUE);
vertex.setDaddy(null);
if (vertex.getLabel().contains(root)) {
rootNode = vertex;
}
}
rootNode.setKey(0);
PriorityQueue<Node> nodePriorityQueue = new PriorityQueue<>();
for (Node vertex: this.weightedGraph) {
nodePriorityQueue.add(vertex);
}
int min = 0;
while (!nodePriorityQueue.isEmpty()) {
Node u = nodePriorityQueue.peek();
LinkedList<Edge> uEdges= u.getEdges();
for (Edge e: uEdges) {
Node v = e.getDestination();
int u_vWeight = e.getWeight();
if (nodePriorityQueue.contains(e.getDestination()) && u_vWeight < v.getKey()) {
v.setDaddy(u);
v.setKey(u_vWeight);
}
}
nodePriorityQueue.remove(u);
min += u.getKey();
}
}
public static void main(String[] args) {
Graph graph = new Graph(9);
String[] nodes = new String[9];
nodes[0] = "a";
nodes[1] = "b";
nodes[2] = "c";
nodes[3] = "d";
nodes[4] = "e";
nodes[5] = "f";
nodes[6] = "g";
nodes[7] = "h";
nodes[8] = "i";
int pos = 0;
for (String s: nodes) {
graph.weightedGraph[pos].setLabel(s);
pos += 1;
}
graph.addEdge("a", "b", 4);
graph.addEdge("a", "h", 9);
graph.addEdge("b", "h", 11);
graph.addEdge("b", "c", 8);
graph.addEdge("h", "i", 7);
graph.addEdge("i", "g", 6);
graph.addEdge("c", "f", 4);
graph.addEdge("c", "d", 7);
graph.addEdge("d", "e", 9);
graph.addEdge("d", "f", 14);
graph.addEdge("e", "f", 10);
graph.addEdge("h", "g", 1);
graph.addEdge("c", "i", 2);
graph.addEdge("g", "f", 2);
graph.minimumSpanningTree("a");
}
}
基本上我有三个类,Node
、Edge
和 Graph
。我在 Node 中包含了一个 Comparator
以允许 PriorityQueue 根据需要重新排序元素。
我构建图表,调用 minimumSpanningTree
,它打印以下 MST:
a
b
c
i
f
d
e
h
g
而不是像我在下面展示的 CLRS 示例中那样执行 a-b-c-i-f-g
:
我真的不明白为什么它选择节点 d
而不是 g
当 g
显然具有最低键时,通过调试检查priorityQueue 证实了这一点。
非常感谢您的帮助。
最佳答案
我想出了我的问题。事实证明,我构建的邻接表表示中的边是有向的。为了解决这个问题,我只是添加了反向边缘,一切都按预期进行。
而且事实证明,优先级队列在删除其中一个元素时不会更新其元素。根据 SO 上关于优先级队列 (PQ) 未更新的一些其他答案,我从 PQ 中删除并添加了节点,这些节点的键在 for 循环内更新。有人有更好的建议吗? minimumSpanningTree
的更新代码如下:
public void minimumSpanningTree(String root) {
ArrayList<Node> msTree = new ArrayList<>();
Node rootNode = null;
for (Node vertex: this.weightedGraph) {
vertex.setKey(Integer.MAX_VALUE);
vertex.setDaddy(null);
if (vertex.getLabel().contains(root)) {
rootNode = vertex;
}
}
rootNode.setKey(0);
PriorityQueue<Node> nodePriorityQueue = new PriorityQueue<>();
for (Node vertex: this.weightedGraph) {
nodePriorityQueue.add(vertex);
}
int min = 0;
while (!nodePriorityQueue.isEmpty()) {
Node u = nodePriorityQueue.peek();
LinkedList<Edge> uEdges= u.getEdges();
for (Edge e: uEdges) {
Node v = e.getDestination();
int u_vWeight = e.getWeight();
if (nodePriorityQueue.contains(e.getDestination()) && u_vWeight < v.getKey()) {
nodePriorityQueue.remove(v);
v.setDaddy(u);
v.setKey(u_vWeight);
nodePriorityQueue.add(v);
}
}
msTree.add(u);
System.out.println(u.getLabel());
nodePriorityQueue.remove(u);
}
编辑:但是,我在边 a-h
和 a-b
方面遇到了同样的问题。我认为它仍然是 MST,但有没有一种方法可以优先访问节点 b
,然后再访问 h
? IE。如果优先级队列中有关系,优先考虑具有较低字母数字优先级的键?
关于java - 在 Java 中实现 Prim 的 MST,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57129248/
我正在尝试用 javascript 创建一个随机迷宫生成器。 可能已经有可用的示例,但我正在尝试自己解决这个问题(好吧,尽可能多) 我遇到的问题是我的脚本只运行了几个 block 然后就停止了。 我认
一 点睛 在生成树的过程中,把已经在生成树中的节点看作一个集合,把剩下的节点看作另外一个集合,从连接两个集合的边中选择一条权值最小的边即可。 二 算法介绍 首先任选一个节点,例如节点1,把它放在集合
“因此,Prim 算法的总时间为 O(V lg V + E lg V) = O(E lg V),这与我们实现 Kruskal 算法的渐进时间相同。” 来自http://serverbob.3x.ro/
def prim(graph): que = queue.PriorityQueue() mst = [] visited = set() # Generate edg
我正在尝试使用优先级队列在 Java 中实现 Prim 的算法。 我找不到我的错误。 :/我只是认识到队列没有正确排序节点。 图表示例: 0 4 7 5 4 0 2 3 7 2 0 1 5 3 1 0
我的算法课正在讨论 Prim 算法作为一种寻找加权图的最小生成树的方法。我们的教授让我们试着想一个图的例子,Prim 的算法需要 N^2 时间来解决(N = 顶点数)。类没有人能凭空想到一个,所以我问
prim 算法的简单实现应该给出 O(mn) 的运行时间。但我在 Prim 函数中有 3 个 for 循环(使运行时间立方)。我哪里出错了? void Graph::Prim (const int s
我正在尝试实现一种近似算法来解决旅行商问题 (TSP),当三角不等式对边权重成立时可以使用该算法。正如 Cormen 等人在算法简介(第 3 3d.)中所述,伪代码是: 这是一个例子: 我苦恼的是如何
我发现 there are two ways to implement Prim algorithm ,并且邻接矩阵的时间复杂度为 O(V^2),而堆和邻接列表的时间复杂度为 O(E lg(V))。
我正在查看 Wikipedia entry对于 Prim 的算法,我注意到它与邻接矩阵的时间复杂度是 O(V^2),它与堆和邻接列表的时间复杂度是 O(E lg(V)),其中 E 是边数,V 是图中的
我正在尝试使用 Prim 的最小生成树算法优化图形。但我没有得到想要的答案。 算法: 1. Construct min heap array. The array consists of nodes
我有以下函数来查找父数组,以便使用 Prim 算法获得图的最小生成树。 #include #include #include int printMST(int parent[], int n, i
Prim 算法思想: 从任意一顶点 v0 开始选择其最近顶点 v1 构成树 T1,再连接与 T1 最近顶点 v2 构成树 T2, 如此重复直到所有顶点均在所构成树中为止。 最小生成树(MST):权值
这个问题在这里已经有了答案: what is the meaning of "let x = x in x" and "data Float#" in GHC.Prim in Haskell (2 个
所以我检查了之前发布的 prims 算法帖子。我找不到一个能满足老师要求的。我和他一起编写了这段代码,并且大部分工作正常。然而,由于某种原因,当它到达某个点时,它会破裂并走向错误的边缘。 '''pub
我必须从 Prim 算法创建一个迷宫,更准确地说是使用这个算法:(随机 Prim 算法)。 http://en.wikipedia.org/wiki/Maze_generation # Randomi
我正在尝试使用 Prim 算法实现一个随机生成的迷宫。但是该程序无法正确生成迷宫。请看看并给我一些建议 这是我的迷宫图片: 迷宫应该是这样的: Prim 算法: private void Prims(
我正在一个项目中使用 Dijkstra 算法,但想尝试使用策略模式实现 Prims 算法,看看它有什么更好的地方,但我不确定如何使用策略模式。我以前从未使用过模式,所以我不知道从哪里开始。 packa
我正在尝试将房间放置在 ASCII 屏幕上,然后使用 Prim's algorithm用迷宫“填充”房间之间的空间,但实际上并没有闯入房间。我已经修补了几个小时,但我无法找到一种方法来阻止我的算法闯入
我正在尝试使用 JGraphT 实现 Prim 的最小生成树算法。看起来怎么样? 我遇到的一个问题是 JGraphT 按照指示处理所有事情。因此,有时需要进行一些尴尬的调用来反转 g.getEdgeS
我是一名优秀的程序员,十分优秀!