shortPath数组和DistantanceParent类。
最短路径算法的关键数据结构是一个数组,它保持了从原点到其他顶点(终点的最短路径)。在算法的执行过程中这个距离是变化的,直到最后,它存储了从原点开始真正的最短距离,在程序中,这个数组叫做shortPath[]. 也就是最短路径
不仅应该记录从原点到终点的最短路径,还应该记录走过的路径。幸运的是,不必要明确记录整个路径,只需要记录终点的父节点。父节点就是达到终点前的节点。有几种方法保存父节点顶点的信息,本程序选用了把父节点和距离放在一起的方法,并把结果的对象放在shortPath[]数组中。这个对象类叫做DistanceParent (距离-父节点)。
class DistanceParent //distance and parent
{
public int distance ;//distance from start to this vertex
public int parentVert; // current parent of this vertex
//.............................
public DistanceParent(int pv, int d)
{
distance = d;
parentVert = pv;
}
}
//.............................................
class Vertex
{
public char label; // label,like 'A'
public boolean isInTree;
//...............................
public Vertex(char lab)
{
label = lab;
isInTree = false;
}
}
//.....................................
class Graph
{
private final int MAX_VERTS = 20;
private final int INFINITY = 10000000; //用一个很大的数代表无穷大
private Vertex vertexList[] ; //list of vertices
private int adjMat[][] ; // 邻接矩阵
private int nVerts; //当前节点数
private int nTree ; //number of verts in tree
private DistanceParent shortPath[] ; //保存最短路径的数组
private int currentVert ; //当前顶点
private int startToCurrent ;//到当前顶点的距离
//.......................................................
public Graph()
{
vertexList = new Vertex[MAX_VERTS];
adjMat = new int[MAX_VERTS][MAX_VERTS];
nVerts = 0;
nTree = 0;
for(int j = 0;j<MAX_VERTS;j++)
for(int k=0;k<MAX_VERTS;k++)
adjMat[j][k] = INFINITY;
shortPath = new DistanceParent[MAX_VERTS];
}
//.............................................
public void addVertex(char lab)
{
vertexList[nVerts++] = new Vertex(lab);
}
//......................................
public void addEdge(int start,int end,int weight)
{
adjMat[start][end] = weight;
}
//.........................
public void path()
{
int startTree = 0; //从第0格节点开始
vertexList[startTree].isInTree = true; // put int tree
nTree = 1;
for(int j = 0;j<nVerts;j++)
{
int tempDistance = adjMat[startTree][j];
shortPath[j] = new DistanceParent(startTree, tempDistance);
//until all vertices are in the tree
}
/* * 1.选择shortPath[] 数组中的最小距离 * 2.把对于的顶点放入树中,这个点变成当前顶点 ,currentVert * 3.根据currentVert的变化,更新所有的shortPath[]数组内容 */
while(nTree <nVerts)
{
int indexMin = getMin();//从shortPath【】数组中获得最短路径
int minDintance = shortPath[indexMin].distance;
if(minDintance == INFINITY)
{
System.out.println("节点不可到达");
break;
}
else
{ // reset currentVert
currentVert = indexMin; //to closest vert
startToCurrent =shortPath[indexMin].distance;
}
//put current vertex in tree
vertexList[currentVert].isInTree= true;
nTree++;
adjust_shortPath(); //更新最短路径数组
}
displayPaths(); //显示最短路径数组内容
nTree = 0; // clear tree
for (int i = 0; i < nVerts; i++)
vertexList[i].isInTree = false;
}
//........................................
public int getMin()
{
int minDistance = INFINITY;
int indexMin = 0;
for(int j = 1;j<nVerts;j++)
{
if(!vertexList[j].isInTree &&shortPath[j].distance <minDistance)
{
minDistance = shortPath[j].distance;
indexMin = j;
}
}
return indexMin;
}
/* * adjust_shortPath()方法更新shortPath[]数组 * 当程序被调用时,currentVert刚被放入树中, * startToCurrent时shortPath[]数组的当前项。adjust_shortPath()方法检查shortPath[] * 中的每一项,它使用循环计数器column依次指向每个顶点。 * 对于shortPath[]数组的每一个项,如果对应顶点不在树中,它做三件事: * 1.把到当前顶点的距离(存在startToCurrent变量中)加到从currentVert顶点到column顶点的距离上 * 结果叫做startToFringe * 2.把startToFringe与shortPath[]数组的当前项进行比较 * 3.如果startToFringe更小,就替换当前项 * * 这就是Dijkstra算法的核心,它让shortPath[]数组总是存储从原点到所有已知顶点的最短路径。 */
public void adjust_shortPath()
{
// adjust values in shortest-path array shortPath
int colunm = 1; //skip starting vertex
while(colunm < nVerts)
{
//if this column vertex already in tree skip it
if(vertexList[colunm].isInTree)
{
colunm++;
continue;
}
//calculate distance for one shortPath entry
//get edge from currentVert to column
int currentToFringe = adjMat[currentVert][colunm];
//add distance from start
int startToFringe =startToCurrent +currentToFringe;
//get distance of current shortPath entry
int shortPathDistance = shortPath[colunm].distance;
//compare distance from start with shortPath entry
if(startToFringe <shortPathDistance) //update
{
shortPath[colunm].parentVert = currentVert;
shortPath[colunm].distance = startToFringe;
}
colunm++;
}
}
//..........................
public void displayPaths()
{
for(int j = 0;j<nVerts;j++)
{
System.out.print(vertexList[j].label + "=");
if(shortPath[j].distance == INFINITY)
System.out.print("inf");
else
System.out.print(shortPath[j].distance);
char parent = vertexList[shortPath[j].parentVert].label;
System.out.print(" ("+parent +") ");
}
System.out.println(" ");
}
}
////////////////////////////////////////////
class PathApp
{
public static void main(String[] args)
{
Graph theGraph = new Graph();
theGraph.addVertex('A'); //0
theGraph.addVertex('B'); //1
theGraph.addVertex('C'); //2
theGraph.addVertex('D'); //3
theGraph.addVertex('E'); //4
theGraph.addEdge(0, 1, 50);
theGraph.addEdge(0, 3, 80);
theGraph.addEdge(1, 2, 60);
theGraph.addEdge(1, 3, 90);
theGraph.addEdge(2, 4, 40);
theGraph.addEdge(3, 2, 20);
theGraph.addEdge(3, 4, 70);
theGraph.addEdge(4, 1, 50);
System.out.println("最短路径:");
theGraph.path();
System.out.println();
}
}