dijkstra算法的java实现
2016-01-05 11:12
411 查看
算法思想: 贪婪算法的一个例子。主要是找到该阶段的一个最优解。首先把结点分为两拨,open(未计算出最小路径的结点),close(已经计算出最小路径的结点)。每次我们都从start结点的子节点中找到一个最短的结点nearest加入,然后更新其未被加入的子节点的距离信息,递归的继续加入,直到start子节点的所有结点都被加入,然后以nearest为节点继续查找,直到所有结点都被加入。算法复杂度为o(v^2)。此算法只针对路径非负。而且边比较多的。如果边数较少的话算法效率会比较低。应该会有更好的算法。
对应java源代码如下:
执行结果如下:
##############################
start:A
nearrest:B
open:D H F C G E #
close:A B
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A 2147483647
F:A->F 2
G:A->G 5
H:A->B->H 5
##############################
start:A
nearrest:C
open:D H F G E #
close:A B C
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A 2147483647
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:A
nearrest:F
open:D H G E #
close:A F B C
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:A
nearrest:D
open:H G E #
close:D A F B C
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:A
nearrest:G
open:H E #
close:D A F B C G
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:G
nearrest:H
open:E #
close:D A H F B C G
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:D
nearrest:E
open:#
close:D A H F B C G E
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
最终结果
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
对应java源代码如下:
import java.util.*; public class Dijkstra { /**结点的数据结构 * 点的名称 * 子节点和到每个子节点的距离的map*/ class Node { private String name; private Map<Node,Integer> child=new HashMap<Node,Integer>(); public Node(String name){ this.name=name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<Node, Integer> getChild() { return child; } public void setChild(Map<Node, Integer> child) { this.child = child; } } /**无向图,需要设置双向的链接*/ public Node build(Set<Node> open, Set<Node> close){ Node nodeA=new Node("A"); Node nodeB=new Node("B"); Node nodeC=new Node("C"); Node nodeD=new Node("D"); Node nodeE=new Node("E"); Node nodeF=new Node("F"); Node nodeG=new Node("G"); Node nodeH=new Node("H"); nodeA.getChild().put(nodeB, 1); nodeA.getChild().put(nodeC, 1); nodeA.getChild().put(nodeD, 4); nodeA.getChild().put(nodeG, 5); nodeA.getChild().put(nodeF, 2); nodeB.getChild().put(nodeA, 1); nodeB.getChild().put(nodeF, 2); nodeB.getChild().put(nodeH, 4); nodeC.getChild().put(nodeA, 1); nodeC.getChild().put(nodeG, 3); nodeD.getChild().put(nodeA, 4); nodeD.getChild().put(nodeE, 1); nodeE.getChild().put(nodeD, 1); nodeE.getChild().put(nodeF, 1); nodeF.getChild().put(nodeE, 1); nodeF.getChild().put(nodeB, 2); nodeF.getChild().put(nodeA, 2); nodeG.getChild().put(nodeC, 3); nodeG.getChild().put(nodeA, 5); nodeG.getChild().put(nodeH, 1); nodeH.getChild().put(nodeB, 4); nodeH.getChild().put(nodeG, 1); /**除了初始结点,其它的结点都加入待定席*/ open.add(nodeB); open.add(nodeC); open.add(nodeD); open.add(nodeE); open.add(nodeF); open.add(nodeG); open.add(nodeH); close.add(nodeA); return nodeA; } Set<Node> open=new HashSet<Node>(); Set<Node> close=new HashSet<Node>(); Map<String,Integer> path=new HashMap<String,Integer>();//封装路径距离 Map<String,String> pathInfo=new HashMap<String,String>();//封装路径信息 public Node init(){ //初始路径,因没有A->E这条路径,所以path(E)设置为Integer.MAX_VALUE path.put("A", 0); pathInfo.put("A", "A->A"); path.put("B", 1); pathInfo.put("B", "A->B"); path.put("C", 1); pathInfo.put("C", "A->C"); path.put("D", 4); pathInfo.put("D", "A->D"); path.put("E", Integer.MAX_VALUE); pathInfo.put("E", "A"); path.put("F", 2); pathInfo.put("F", "A->F"); path.put("G", 5); pathInfo.put("G", "A->G"); path.put("H", Integer.MAX_VALUE); pathInfo.put("H", "A"); //将初始节点放入close,其他节点放入open Node start=build(open,close); return start; } public void computePath(Node start){ Node nearest=getShortestPath(start);//取距离start节点最近的子节点,放入close if(nearest==null){ return; } close.add(nearest); open.remove(nearest); /**每次加入一个结点,需要查看是否更新其距离信息*/ Map<Node,Integer> childs=nearest.getChild(); for(Node child:childs.keySet()){ if(open.contains(child)){//如果子节点在open中 Integer newCompute=path.get(nearest.getName())+childs.get(child); if(path.get(child.getName())>newCompute){//之前设置的距离大于新计算出来的距离 path.put(child.getName(), newCompute); pathInfo.put(child.getName(), pathInfo.get(nearest.getName())+"->"+child.getName()); } } } System.out.println("##############################"); System.out.println("start:"+start.name); System.out.println("nearrest:"+nearest.name); System.out.print("open:"); for(Node node:open) { System.out.print(node.name+" "); } System.out.println("#"); System.out.print("close:"); for(Node node:close) { System.out.print(node.name+" "); } System.out.println(); printPathInfo(); computePath(start);//重复执行自己,确保所有子节点被遍历 computePath(nearest);//向外一层层递归,直至所有顶点被遍历 } public void printPathInfo(){ Set<Map.Entry<String, String>> pathInfos=pathInfo.entrySet(); for(Map.Entry<String, String> pathInfo:pathInfos){ System.out.println(pathInfo.getKey()+":"+pathInfo.getValue()+" "+path.get(pathInfo.getKey())); } } /** * 获取与node最近的子节点 */ private Node getShortestPath(Node node){ Node res=null; int minDis=Integer.MAX_VALUE; Map<Node,Integer> childs=node.getChild(); for(Node child:childs.keySet()){ if(open.contains(child)){ int distance=childs.get(child); if(distance<minDis){ minDis=distance; res=child; } } } return res; } public static void main(String[] args) { Dijkstra test=new Dijkstra(); Node start=test.init(); test.computePath(start); System.out.println("##############################"); System.out.println("最终结果"); test.printPathInfo(); } }
执行结果如下:
##############################
start:A
nearrest:B
open:D H F C G E #
close:A B
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A 2147483647
F:A->F 2
G:A->G 5
H:A->B->H 5
##############################
start:A
nearrest:C
open:D H F G E #
close:A B C
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A 2147483647
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:A
nearrest:F
open:D H G E #
close:A F B C
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:A
nearrest:D
open:H G E #
close:D A F B C
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:A
nearrest:G
open:H E #
close:D A F B C G
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:G
nearrest:H
open:E #
close:D A H F B C G
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
start:D
nearrest:E
open:#
close:D A H F B C G E
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
##############################
最终结果
A:A->A 0
B:A->B 1
C:A->C 1
D:A->D 4
E:A->F->E 3
F:A->F 2
G:A->C->G 4
H:A->B->H 5
相关文章推荐
- 使用IntelliJ IDEA 14和Maven创建java web项目
- Java的概述
- Maven学习总结(12)——eclipse中构建多模块maven项目
- Spring 基础实例1
- Spring+Quartz实现定时任务的配置方法
- java web springMVC response wirte image demo
- JAVA 的 mysql blob操作 -1 比较全面,但是格式乱
- 简单说说Spring Security 使用(附加验证码登录,自定义认证)
- 添加Java文档注释
- Java内存模型:线程并发下的对象逸出
- Myeclipse10破解 注册之前找不到common文件夹的问题
- 【Java并发编程实战】- Lock
- 为什么写Java程序需要接口
- 【Java并发编程实战】- Synchronized
- Java 多线程 并发编程
- Java中反射的用法
- Spring 基础 实例
- eclipse快捷键总结
- JAVA Map集合类简介
- Posting JSON to Spring MVC Controller