返回信息流这个程序实现了Dijkstra算法(最短路径遍历图)。
这个实现使用了观察者(Observer)模式。外部可以给UndirectedGraph添加观察者(addVisitor),每次遍历到一个节点,会输出该节点以及它到原点的最短路径。
使用观察者模式是因为图会很大,不方便把结果全部存起来再统一遍历。
******* 其实下面才是脑残问题 ********
谁能把这个visitor转换成一个for循环?
for (NodeAndDistance nad : graph.dijkstraOrder()) {
System.out.println(.....);
}
*********************************
代码在下面
package graphwalk;
import java.util.*;
class Node {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Node(String name) {
super();
this.name = name;
}
}
interface NodeVisitor {
void visit(Node node, double shortestDistance);
}
class UndirectedGraph {
private HashMap<Node, Map<Node, Double>> adjacencyMap = new HashMap<Node, Map<Node, Double>>();
private Node origin;
private List<NodeVisitor> nodeVisitors = new ArrayList<NodeVisitor>();
public Node getOrigin() {
return origin;
}
public void setOrigin(Node origin) {
this.origin = origin;
}
public void addVisitor(NodeVisitor e) {
nodeVisitors.add(e);
}
public void removeVisitor(NodeVisitor e) {
nodeVisitors.remove(e);
}
public void addNode(Node node) {
if (!adjacencyMap.containsKey(node)) {
adjacencyMap.put(node, new HashMap<Node, Double>());
}
}
public void addEdge(Node from, Node to, double weight) {
addNode(from);
addNode(to);
adjacencyMap.get(from).put(to, weight);
adjacencyMap.get(to).put(from, weight);
}
private class QueueEntry implements Comparable<QueueEntry> {
public Double distance;
public Node node;
public QueueEntry(Double distance, Node node) {
super();
this.distance = distance;
this.node = node;
}
@Override
public int compareTo(QueueEntry o) {
return distance.compareTo(o.distance);
}
}
// Why not "run", instead? (And then implement Runnable)
public void walk() {
final PriorityQueue<QueueEntry> queue = new PriorityQueue<QueueEntry>();
final Set<Node> visitedNodes = new HashSet<Node>();
final Map<Node, Double> distances = new HashMap<Node, Double>();
distances.put(origin, 0.0);
queue.add(new QueueEntry(0.0, origin));
while (!queue.isEmpty()) {
QueueEntry entry = queue.remove();
Double currentDistance = entry.distance;
Node currentNode = entry.node;
if (!visitedNodes.contains(currentNode)) {
for (NodeVisitor visitor : nodeVisitors) {
visitor.visit(currentNode, currentDistance);
}
visitedNodes.add(currentNode);
distances.put(currentNode, currentDistance);
Map<Node, Double> adjacentNodes = adjacencyMap.get(currentNode);
for (Node newNode : adjacentNodes.keySet()) {
double newDistance = currentDistance
+ adjacentNodes.get(newNode);
if (!distances.containsKey(newNode)
|| distances.get(newNode) > newDistance) {
distances.put(newNode, newDistance);
queue.add(new QueueEntry(newDistance, newNode));
}
}
}
}
// dist.put(here, 0.0);
}
}
class NodePrintingVisitor implements NodeVisitor {
@Override
public void visit(Node node, double shortestDistance) {
System.out.println(node.getName() + " " + shortestDistance);
}
}
public class DijkstraDemo {
public static void main(String[] args) {
UndirectedGraph g = new UndirectedGraph();
Node beijing = new Node("Beijing");
Node tianjin = new Node("Tianjin");
Node shanghai = new Node("Shanghai");
Node wuhan = new Node("Wuhan");
Node xian = new Node("Xi'an");
Node guangzhou = new Node("Guangzhou");
g.addNode(beijing);
g.addNode(tianjin);
g.addNode(shanghai);
g.addNode(wuhan);
g.addNode(xian);
g.addNode(guangzhou);
g.addEdge(beijing, tianjin, 2.0);
g.addEdge(beijing, wuhan, 10.0);
g.addEdge(beijing, xian, 15.0);
g.addEdge(tianjin, shanghai, 12.0);
g.addEdge(xian, wuhan, 8.0);
g.addEdge(wuhan, shanghai, 10.0);
g.addEdge(xian, guangzhou, 10.0);
g.addEdge(wuhan, guangzhou, 8.0);
g.addEdge(shanghai, wuhan, 15.0);
g.setOrigin(beijing);
g.addVisitor(new NodePrintingVisitor());
g.walk();
}
}
这是一条镜像帖。来源:北邮人论坛 / java / #16742同步于 2010/12/7
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
不怕脑残的继续进
wks
2010/12/7镜像同步4 回复
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
nc三部曲了,先sf
慢慢看
【 在 wks (cloverprince) 的大作中提到: 】
: 这个程序实现了Dijkstra算法(最短路径遍历图)。
: 这个实现使用了观察者(Observer)模式。外部可以给UndirectedGraph添加观察者(addVisitor),每次遍历到一个节点,会输出该节点以及它到原点的最短路径。
: 使用观察者模式是因为图会很大,不方便把结果全部存起来再统一遍历。
: ...................
【 在 wks 的大作中提到: 】
: 这个程序实现了Dijkstra算法(最短路径遍历图)。
: 这个实现使用了观察者(Observer)模式。外部可以给UndirectedGraph添加观察者(addVisitor),每次遍历到一个节点,会输出该节点以及它到原点的最短路径。
: 使用观察者模式是因为图会很大,不方便把结果全部存起来再统一遍历。
: ...................
转化成for循环,也就是打印路径信息的时候只需要运行一次visit呗。这样的话。。。和“图会很大,不方便把结果全部存起来再统一遍历”矛盾了呀
如果是python的话:
def visit_graph(g):
...
while queue is not empty:
node=....
yield (node, distance)
for node, distance in visit_graph(g):
....
实际上只要让这个for循环变得懒惰,图大,空间不够的问题就可以解决了。
【 在 wks 的大作中提到: 】
: 如果是python的话:
: def visit_graph(g):
: ...
: ...................
yield是很爽~往往某些语言的语法就是另外一些语言的设计模式。。。
不过还是要维护一个queue,以queue是否为空作为遍历是否结束的条件,这个用java代码也完全可以实现。