面试时遇到Dijkstra算法,这个算法我是知道的,但是没具体写过,所以答题比较慢,抽时间实现了下这个算法。
Dijkstra算法基本思路:
该算法的基本思路是这样的,从起始点开始,将未访问过的相邻节点加入一个优先队列,类似于广度优先算法,然后从该队列中取出节点考虑:
对于单个节点,找出其所有相邻边,对于其邻接节点,计算总长度,如果该邻接节点的长度大于从该节点的长度,则更新路径为该节点。
具体代码如下:
package src.arithmetic;
import java.util.*;
import java.util.Map.Entry;
/**
* Dijkstra算法
*/
public class Dijkstra
{
public static class Node
{
public int nodeId;//节点标识
public List<Edge> adjEdge;//相邻边边
public Node(int nodeId, List<Edge> adjEdge) {
this.nodeId = nodeId;
this.adjEdge = adjEdge;
}
}
/**
* 发出边
*/
public static class Edge
{
public int endNode;//终止节点
public int weigth;//边的权重
public Edge(int endNode,int weigth)
{
this.endNode=endNode;
this.weigth=weigth;
}
}
Map<Integer,Node> graph;//图
private Node startNode;//起始点
private Map<Integer,Integer> distTo;//记录当前最短距离
private Queue<Node> pq;//优先队列
public Dijkstra(Map graph,Node startNode)
{
this.graph=graph;
this.startNode=startNode;
distTo=new HashMap<>();
pq=new LinkedList<>();
}
/**
* Dijkstra算法主体
*/
public void gogogo()
{
//从起始点开始
pq.offer(startNode);
distTo.put(startNode.nodeId,0);
while(!pq.isEmpty())
{
Node tempNode = pq.peek();
pq.remove();
int curLen=distTo.get(tempNode.nodeId);
//对于所有相邻边
for (Edge nextEdge:tempNode.adjEdge)
{
//如果还没被访问过,则暂时设置为从当前节点到此为最短距离。同时将该点记录到pq(广度优先)
if(distTo.get(nextEdge.endNode) == null)
{
pq.offer(graph.get(nextEdge.endNode));
distTo.put(nextEdge.endNode, curLen + nextEdge.weigth);
}
//如果当前节点被访问过,但不是最短路径,则更新。
else if(distTo.get(nextEdge.endNode) > curLen + nextEdge.weigth)
{
distTo.put(nextEdge.endNode, curLen + nextEdge.weigth);
}
}
}
System.out.println("从节点:" + startNode.nodeId +"开始,到达其他节点的最短距离分别为:");
for(Entry<Integer,Integer> entry : distTo.entrySet())
{
System.out.println("到节点: " + entry.getKey() + "距离为 : " + entry.getValue());
}
}
//测试用例
public static void main(String[] args)
{
Map<Integer,Node> testGraph = new HashMap<>();
Edge e04 = new Edge(4,38);
Edge e02 = new Edge(2, 26);
Edge e27 = new Edge(7, 34);
Edge e47 = new Edge(7, 37);
Edge e45 = new Edge(5, 35);
Edge e54 = new Edge(4, 35);
Edge e57 = new Edge(7, 28);
Edge e75 = new Edge(5, 28);
Edge e51 = new Edge(1, 32);
Edge e73 = new Edge(3, 39);
Edge e13 = new Edge(3, 29);
Edge e62 = new Edge(2, 40);
Edge e36 = new Edge(6, 52);
Edge e60 = new Edge(0, 58);
Edge e64 = new Edge(2, 93);
List<Edge> l0 = new LinkedList<>();
l0.add(e02);
l0.add(e04);
List<Edge> l1 = new LinkedList<>();
l1.add(e13);
List<Edge> l2 = new LinkedList<>();
l2.add(e27);
List<Edge> l3 = new LinkedList<>();
l3.add(e36);
List<Edge> l4 = new LinkedList<>();
l4.add(e45);
l4.add(e47);
List<Edge> l5 = new LinkedList<>();
l5.add(e51);
l5.add(e54);
l5.add(e57);
List<Edge> l6 = new LinkedList<>();
l6.add(e60);
l6.add(e62);
l6.add(e64);
List<Edge> l7 = new LinkedList<>();
l7.add(e73);
l7.add(e75);
Node n0= new Node(0,l0);
Node n1= new Node(1,l1);
Node n2= new Node(2,l2);
Node n3= new Node(3,l3);
Node n4= new Node(4,l4);
Node n5= new Node(5,l5);
Node n6= new Node(6,l6);
Node n7= new Node(7,l7);
testGraph.put(0,n0);
testGraph.put(1,n1);
testGraph.put(2,n2);
testGraph.put(3,n3);
testGraph.put(4,n4);
testGraph.put(5,n5);
testGraph.put(6,n6);
testGraph.put(7,n7);
Dijkstra dijkstra =new Dijkstra(testGraph,n0);
dijkstra.gogogo();
}
}