Dijkstra算法的Java实现

时间:2022-04-26 11:00:56

Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

  Dijkstra算法是很有代表性的最短路算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。

其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。

初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。

例如,对下图中的有向图,应用Dijkstra算法计算从源顶点1到其它顶点间最短路径的过程列在下表中。

Dijkstra算法的Java实现
Dijkstra算法的迭代过程:

Dijkstra算法的Java实现

代码实现:

package com.teradata.lsw.sort;


/**
 * 
 * @author TD_LSW
 *
 */
public class Dijkstra {
public static void main(String[] args) {
Graphs theGraph = new Graphs();
char[] vertices = { 'A', 'B', 'C', 'D', 'E', 'F' };
//初始化节点信息
theGraph.addVertex(vertices);
//设置边和权重
theGraph.addOneEdge(0, 1, 50);// AB 50
theGraph.addOneEdge(0, 3, 80);// AD 80
theGraph.addOneEdge(1, 2, 60);// BC 60
theGraph.addOneEdge(1, 3, 90);// BD 90
theGraph.addOneEdge(2, 4, 40);// CE 40
theGraph.addOneEdge(3, 2, 20);// DC 20
theGraph.addOneEdge(3, 4, 70);// DE 70
theGraph.addOneEdge(4, 1, 50);// EB 50
theGraph.addOneEdge(4, 5, 30);// EF 30
theGraph.addOneEdge(5, 3, 50);// FD 50


System.out.println("Dijkstra算法实现: ");
theGraph.dijkstra();
}


}
//存放节点信息(是否已经加入最短路径节点)
class Vertex {
public char label;
public boolean isInTree;


public Vertex(char label) {
this.label = label;
isInTree = false;
}
}


//用来存储父节点和距离信息。
class DistPare {
public int parentVertex;
public int distance;


public DistPare(int parentVertex, int distance) {
this.parentVertex = parentVertex;
this.distance = distance;
}
}


class Graphs {
private final int MAX_VERTEX = 20;
private final int INFINITY = 999999;
private int nVerts;
private int nTree;
private int currentVertex;
private int startToCurrent;
private int adjMatrix[][];
private Vertex vertexList[];
//sPath[]用来存储父节点和距离信息。
private DistPare sPath[];


//初始化有向图
public Graphs() {
adjMatrix = new int[MAX_VERTEX][MAX_VERTEX];
vertexList = new Vertex[MAX_VERTEX];
sPath = new DistPare[MAX_VERTEX];
nVerts = 0;
nTree = 0;
for (int i = 0; i < MAX_VERTEX; i++)
for (int j = 0; j < MAX_VERTEX; j++)
adjMatrix[i][j] = INFINITY;
}


//添加节点信息
public void addVertex(char[] vertices) {
for(int i = 0;i<vertices.length;i++){
vertexList[nVerts++] = new Vertex(vertices[i]);
}
}


// 有向图
public void addOneEdge(int start, int end, int weight) {
adjMatrix[start][end] = weight;
}


//具体算法实现
public void dijkstra() {
int startTree = 0;
vertexList[startTree].isInTree = true;
nTree = 1;
for (int j = 0; j < nVerts; j++) {
int tempDist = adjMatrix[startTree][j];
sPath[j] = new DistPare(startTree, tempDist);
}
while (nTree < nVerts) {
int indexMin = getMin();
int minDist = sPath[indexMin].distance;
if (minDist == INFINITY) {
System.out.println("有无法到达的顶点");
} else {
currentVertex = indexMin;
startToCurrent = sPath[indexMin].distance;
}
vertexList[currentVertex].isInTree = true;
nTree++;
//调整最短路径的父节点和权重信息
adjust_sPath();
}
//输出最短路径节点信息
displaypaths();
}


//输出最短路径节点信息
private void displaypaths() {
for (int j = 0; j < nVerts; j++) {
System.out.print(vertexList[j].label + "=");
if (sPath[j].distance == INFINITY)
System.out.print("inf");
else
System.out.print(sPath[j].distance);
char parent = vertexList[sPath[j].parentVertex].label;
System.out.print("(" + parent + ") ");
}
System.out.println(" ");
}

//调整最短路径的父节点和权重信息
private void adjust_sPath() {
int column = 1;
while (column < nVerts) {
if (vertexList[column].isInTree) {
column++;
continue;
}
int currentToFringe = adjMatrix[currentVertex][column];
int startToFringe = startToCurrent + currentToFringe;
int sPathDist = sPath[column].distance;
if (startToFringe < sPathDist) {
sPath[column].parentVertex = currentVertex;
sPath[column].distance = startToFringe;
}
column++;
}
}


//获得最小权重路径的下标
private int getMin() {
int minDist = INFINITY;
int indexMin = 0;
for (int j = 0; j < nVerts; j++) {
if (!vertexList[j].isInTree && sPath[j].distance < minDist) {
minDist = sPath[j].distance;
indexMin = j;
}
}
return indexMin;
}


}