今天又翻了翻算法导论,看了看dijstra算法。兴趣来了就实现了下。完全按照书上的步骤实现,没有使用最小堆等数据结构,使用的邻接表方式表示图。因此实现的算法效率很抵,不过这里只是想通过程序来说明这个算法。不是工程上用的。如果工程上使用,最好用矩阵表示图,然后再使用最小堆。。。。不多说了,直接上代码。
(原理参见算法导论第二版p366)
package Graph; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Stack; public class Dijkstra2 { private AdjacencyList adjList = new AdjacencyList(); public static void main(String[] args) { try{ double[][] matrix = { { util.max, 5, util.max, util.max, 10 }, { util.max, util.max, 2, 9, 3 }, { 7, util.max, util.max, 6, util.max }, { util.max, util.max, 4 , util.max, util.max }, { util.max, 2, util.max, 1, util.max } }; Dijkstra2 dijkstra = new Dijkstra2(matrix); dijkstra.adjList.print(); dijkstra.calculate(0); dijkstra.print(); }catch(Exception e){ e.printStackTrace(); } } public Dijkstra2(double [][] matrix){ adjList = new AdjacencyList(matrix); } //存储前驱节点 private int [] pre ; //存储距离 private double [] dist; /** * @function 计算最近路径 * @param v 源点 */ public void calculate(int v){ pre = new int [this.adjList.size()]; dist = new double[this.adjList.size()]; //s序列,存放 boolean [] s = new boolean [this.adjList.size()]; //初始化距离 Arrays.fill(dist, util.max); //初始化前驱节点 Arrays.fill(pre, -1); //初始队列s中没有点 Arrays.fill(s, false); //源点的距离为0 dist[v] = 0; int gray = v; while(true){ //找出距离最小的点 double mindis = Double.MAX_VALUE; for(int i = 0 ; i < dist.length ; i++){ if(mindis > dist[i] && !s[i]){ mindis = dist[i]; gray = i; } } //把找到的这个点加入到s队列中 s[gray] = true; //======对与gray点有边的点进行松驰===== Node pnode = adjList.get(gray); //向后移一个节点,因为第一个节点是自己。后面的点才是当前节点的后继节点。 pnode = pnode.next; while(pnode != null){ //后继节点与当前节点的距离 + 当前节点与源点的距离 < 后继节点到源点的距离 if(pnode.weight + mindis < dist[pnode.index]){ //后继节点的到源点的距离 更新 为 后继节点与当前节点的距离 + 当前节点与源点的距离 dist[pnode.index] = pnode.weight + mindis; //后继节点的前驱节点更新为 当前节点 pre[pnode.index] = adjList.get(gray).index; } //下一个后继节点 pnode = pnode.next; } //===判断s中是否包含全部的点了 boolean con = false; for(boolean b : s) if(b == false){ con = true; break; } if(!con) break; } } public void print() { for(int i = 0 ; i < dist.length ; i++){ System.out.print(dist[i] + " "); printpath(i); System.out.println(); } } public void printpath(int v){ Stack<Integer> stack = new Stack<Integer>(); while(pre[v] >= 0){ stack.add(pre[v]); v = pre[v]; } while(stack.size() > 0) System.out.print(stack.pop() + " "); } public double getWeight(Node node , int index){ while(node != null){ int ndx = node.index; if(ndx == index) return node.weight; node = node.next; } return util.max; } } class AdjacencyList{ private List<Node> adjList = new ArrayList<Node>(); public AdjacencyList(){}; public int size(){ return adjList.size(); } public Node get(int index){ return this.adjList.get(index); } public List<Node> getData(){ return this.adjList; } public AdjacencyList(double [][] matrix){ for(int i = 0 ; i < matrix.length ; i++){ double [] vals = matrix[i]; addData(i , vals); } } public void addData(int v , double [] vals){ Node node = new Node(v , 0); Node head = node; for(int j = 0 ; j < vals.length ; j++){ if(vals[j] < util.max && vals[j] != 0.0){ node.next = new Node(); node = node.next; node.set( j , vals[j]); } } adjList.add(head); } public void print(){ for(Node node : adjList){ while(node != null){ System.out.print(node.toString() + " "); node = node.next; } System.out.println(); } } } class Node{ Node next; double weight = util.max; int index = -1; public Node(){ } public Node(int index , double weight){ set(index , weight); } public void set(int index , double weight){ this.index = index; this.weight = weight; } @Override public String toString() { // TODO Auto-generated method stub return "[ " + index + " , " + weight + " ]"; } } class util{ public static double max = Double.MAX_VALUE; }