Java新手。
我想要的是一个代表城市的有向图。大多数顶点只是街道,但有些是具有权重的旅游景点(因为必须留在那里一段时间)。我正在使用Dijkstra的最短路径算法,并且已经制作了一些用于添加顶点的版本'权衡它。
然而,问题在于,当我将顶点设置为巡视站点并赋予其权重时,顶点在首次访问时似乎根本没有权重。然后,当第二次访问顶点时,重量显示出来。我不知道问题出在哪里,但我会猜测这是我不是直接编辑原始变量的地方。
打印输出行标在* *之间。一个是 calculateShortest(),另一个是 calculateMin()。
public class Graph
{
protected HashMap<Integer, GraphNode> ntable = new HashMap<Integer, GraphNode>();
//a hashmap of every node's edge treemap, in which edges are sorted according to weight of each
protected HashMap<Integer, TreeMap<Integer, GraphEdge>> etable = new HashMap<Integer, TreeMap<Integer,GraphEdge>>();
}
public class GraphNode
{
private int val;
private boolean site;
private boolean hotel;
private int time;
private int distance = Integer.MAX_VALUE;
private LinkedList<GraphNode> shortest = new LinkedList<GraphNode>();
}
public class GraphEdge implements Comparable<GraphEdge>
{
private int nd1;
private int nd2;
private int weight;
}
public class Path
{
protected LinkedList<GraphNode> path = new LinkedList<GraphNode>();
Graph g = new Graph();
GraphNode start = new GraphNode(0);
protected HashSet<GraphNode> settled = new HashSet<GraphNode>();
protected HashSet<GraphNode> unsettled = new HashSet<GraphNode>();
public Graph calculateShortest(int start)
{
g.ntable.get(start).setDist(0);
unsettled.add(g.ntable.get(start));
while (unsettled.size() != 0)
{
GraphNode current = getLowestCostNode(unsettled);
unsettled.remove(current);
TreeMap<Integer, GraphEdge> adjacentE = g.etable.get(current.getVal());
*
//printing out below shows vertex has no weight
System.out.println("Curr: "+ current.getVal() + " " + current.getSiteTime());
*
for (GraphEdge edge: adjacentE.values())
{
GraphNode adjacent = g.ntable.get(edge.getEnd());
int cost = edge.getWeight() + current.getSiteTime();
if (!settled.contains(adjacent))
{
calculateMin(adjacent, cost, current);
unsettled.add(adjacent);
}
}
settled.add(current);
}
return g;
}
public GraphNode getLowestCostNode(HashSet<GraphNode> unsettled)
{
GraphNode lowestDistNd = null;
int lowestDist = Integer.MAX_VALUE;
for (GraphNode nd : unsettled)
{
int nodeDist = nd.getDist();
if (nodeDist < lowestDist)
{
lowestDist = nodeDist;
lowestDistNd = nd;
}
}
return lowestDistNd;
}
public void calculateMin(GraphNode evaNd, int cost, GraphNode startNd)
{
int startDist = startNd.getDist();
if (startDist + cost < evaNd.getDist())
{
evaNd.setDist(startDist + cost);
LinkedList<GraphNode> shortest = new LinkedList<GraphNode>(startNd.getShortest());
shortest.add(startNd);
evaNd.setShortest(shortest);
*
//print out if the node's distance is changed
System.out.println("Change " + evaNd.getVal() + " " + evaNd.getDist());
*
}
}
}
显示问题的行打印输出(不包括主方法输出):
Curr: 1 0
Change: 2 10
Change: 3 15
Curr: 2 0
Change: 4 22
Change: 6 25
Curr: 3 0
Change: 5 25
Curr: 4 0 //1st time visiting shows no weight
Change: 6 23
Change: 5 24
Curr: 6 0
Curr: 5 0
Curr: 1 0
Curr: 2 0
Curr: 3 0
Curr: 4 30 //2nd time visiting shows weight
Curr: 6 0
Curr: 5 0
对于每个顶点, getDist()返回从源顶点到自身的距离, getCost()返回距离加上权重顶点。
我的主要方法如下。 addNodeEdge()已经过测试,可以很好地运行。我在Dijkstra Algorithm in Java使用示例(见下图),在我的情况下ABCDEF是123456。除了图表,我试图将D(这是顶点4)作为权重为30 的网站。 Visualization of the graph
public static void main (String [] args){
Path p = new Path();
p.g.addNodeEdge(1, 2, 10);
p.g.addNodeEdge(1, 3, 15);
p.g.addNodeEdge(2, 4, 12);
p.g.addNodeEdge(2, 6, 15);
p.g.addNodeEdge(3, 5, 10);
p.g.addNodeEdge(4, 6, 1);
p.g.addNodeEdge(4, 5, 2);
p.g.addNodeEdge(6, 5, 5);
p.calculateShortest(1);
System.out.println(p.g.ntable.get(5).getDist());//print out 24
p.settled.clear();
p.unsettled.clear();
p.g.ntable.get(4).setSite(30);
p.calculateShortest(1);
System.out.println(p.g.ntable.get(5).getDist());//still print out 24
}
我期望到E(顶点5)30和F(顶点6)25的最短路径,因为通过D(顶点4)的权重为30的路径太大。然而,在我改变D的重量之前,我在这里得到的东西是完全相同的,然后才增加了D 的重量。就像我上面解释的那样,我认为问题在于D的体重变化......任何帮助都会非常感激。
答案 0 :(得分:0)
即使您正在清除已结算和未结算的HashSets,跟踪到目前为止找到的最短路径的变量是GraphNode实例变量距离。在第一次运行calculateShortest之后,节点5的距离不会从值24重置,并且在将节点4的站点时间设置为30之后调用该方法后,当然将保持相同。
一种可能的解决方案是更改calculateShortest()的开头以重置所有节点距离:
public Graph calculateShortest(int start) {
for (GraphNode n : g.ntable.values()) {
n.setDist(Integer.MAX_VALUE);
}
g.ntable.get(start).setDist(0);
...
此外,花了一些时间来解决这个问题,主要是因为你发布的代码格式很糟糕。下次请避免发布嵌套类,并且还要包括所有可能不相关的实现细节,这些细节不是普通的getter / setter(例如addNodeEdge)。你永远不知道那个讨厌的bug可能隐藏在哪里!