最短路径算法属于数据结构的图的应用知识。先介绍基本的图的概念。
图由顶点集和边集组成。(一张图里不就是有顶点和边)。图中边带有方向就是有向图,否则就是无向图。图的存储结构分为邻接表和邻接矩阵。(邻接表主要采用顺序存储和链式存储结合的方式)。采用链接表这种都是对于稀疏图而言的(就是边少对应也就权值少的这种图叫稀疏图),而我采用的是邻接矩阵,因为我的那个图是个稠密图,边的权值很多。采用邻接矩阵存储就是两个方面,一个是用一维数组存储顶点信息,一个是用二位数组存储边的权值信息。
int[][] graph = {
{max,221,294,288,max,400,144,219,264,352,462,484},
{max,max,175,97,306,289,166,94,228,258,349,364},
{max,max,max,257,464,462,316,275,405,436,523,538},
{max,max,max,max,205,203,183,79,184,178,256,269},
{max,max,max,max,max,83,318,243,225,126,83,79},
{max,max,max,max,max,max,260,207,152,49,60,84},
{max,max,max,max,max,max,max,107,124,213,321,343},
{max,max,max,max,max,max,max,max,130,167,269,285},
{max,max,max,max,max,max,max,max,max,103,204,230},
{max,max,max,max,max,max,max,max,max,max,108,132},
{max,max,max,max,max,max,max,max,max,max,max,26},
{max,max,max,max,max,max,max,max,max,max,max,max}
};
实际上对于图的遍历分为深度优先搜索和广度优先搜索,而深度优先搜索主要就是尽可能深的去遍历,采用递归的方式。如果了解树的应用中的回溯法和剪支函数就会对递归有很好了解。而我需要对任意一层访问,所以采用广度优先搜索其实和那个树的层序遍历很像。层序遍历需要一个那种暂存的容器记忆正在访问顶点的下一层节点。这种暂存容器就是先进先出的辅助队列。而我的队列都是用一维数组实现的。
最短路径算法思想:
从第一个节点V1开始遍历,就是遍历权值矩阵中第一行权值。找出距离V1最短的节点V2。V1到V2的最短距离为D1,然后从V2开始遍历到其他节点的最短距离,就是遍历权值矩阵中V2所在的行,找出距离V2最短的点V3,最短权值为D2。然后一直遍历到最后一个点。并且还设置一个标记位,标记那些已经访问过的点,就不会被再次访问。我设置访问过的点位true,否则为false。但是还需要考虑一种情况:假设V3到V1的D3,此时D3>D1+D2这种情况问题的实质就是当前选择的直接到的路径比拐一个点再到终点的路径还长,不是最短路径,所以,要加入到整体遍历的情况中进行判断。然后就慢慢遍历吧。
关键代码:
static int MAX_SIZE=12;
private static int[] stationTemp=new int[MAX_SIZE];//存储最短路径经过的点(不包括起始点和终点),如果没有就都设置为0
private static int[] dist=new int[MAX_SIZE];// 最短路径长度
private static int[] prev=new int[MAX_SIZE];// 前驱顶点集合;
/**最短路径算法
* @param args
*/
public static void dijkstra(int start,int[][] graph,int[] dist,int[] prev){
int n=dist.length-1;
if(start<1||start>n)
return;
boolean[] marked=new boolean[n+1];//标记
for(int i=1;i<=n;i++){
dist[i]=graph[start][i];
marked[i]=false;
if(dist[i]==Integer.MAX_VALUE){
prev[i]=0;//将所有节点的前驱都设置为空(除了最后一个节点)
}else{
prev[i]=start;//最后一个节点的前驱为第一个开始遍历的节点
}
}
dist[start]=0;
marked[start]=true;//从start点开始遍历
for(int i=1;i