dijkstra算法的java实现

算法思想: 贪婪算法的一个例子。主要是找到该阶段的一个最优解。首先把结点分为两拨,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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值