今天又翻了翻算法导论,看了看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] + "\t");
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() + "\t");
}
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() + "\t");
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;
}