您的位置:首页 > 编程语言 > Java开发

dijkstra算法的java实现

2016-01-05 11:12 411 查看
算法思想: 贪婪算法的一个例子。主要是找到该阶段的一个最优解。首先把结点分为两拨,open(未计算出最小路径的结点),close(已经计算出最小路径的结点)。每次我们都从start结点的子节点中找到一个最短的结点nearest加入,然后更新其未被加入的子节点的距离信息,递归的继续加入,直到start子节点的所有结点都被加入,然后以nearest为节点继续查找,直到所有结点都被加入。算法复杂度为o(v^2)。此算法只针对路径非负。而且边比较多的。如果边数较少的话算法效率会比较低。应该会有更好的算法。

对应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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: