最短路径算法是图论中的常见问题,在实际中有着较为广泛的应用,比如查找从一个地方到另一个地方的最快方式。问题可以概括为,对于某个输入顶点s,给出s到所有其它顶点的最短路径。水平有限,暂时先对这个问题的求解做简单记录。
无权图是有权最短路径的特例,即边的权重均是1。算法类似于BFS(宽度优先搜索),在实现时需要一个宽度优先搜索的队列。全局变量Distance用来保存所有点到输入顶点的距离。以邻接表表示图,无权图最短路径算法:
//无权图的最短路径算法
static void UnweightedShortestPath(Graph g, int start){
Queue<Integer> Q = new LinkedList<Integer>();
int v,w;
Q.offer(start);
g.getVertics().get(start).setVivited(true); //输入顶点被标记为已访问
for(int i=0;i<g.getVertexCount();i++)
Distance[i] = -1; //初始化Distance,都为-1
Distance[start] = 0;
while(!Q.isEmpty()){
v = Q.remove(); //v是队首的整数,记录了图中顶点的序号
while(g.getAdjUnvisitedVertex(v)!=-1){ //寻找顶点v指向的所有的点
w = g.getAdjUnvisitedVertex(v);
g.getVertics().get(w).setVivited(true); //图的对应部分标记为已访问,每个顶点只能被访问一次
if(Distance[w] == -1){
Distance[w] = Distance[v]+1;
Path[w] = v;
Q.offer(w);
}
}//while
}//while
}
Dijkstra算法是解决最短路径问题的常见算法,过程需要使用优先队列来代替无权图最短路径算法。源点到某个顶点的距离为从源点到该顶点的路径上的所有边权值之和,当新计算得到的距离小于原有的距离时,更新距离。
//Dijkstra算法
static void Dijkstra(Graph g, int start){
MinHeap PQ = new MinHeap(10, 0); //最小堆实现优先队列
int v,w;
PQ.Insert(new NodeWithProority(0,0));//NodeWithprority是一个只包括顶点的序号和权值(到给定起始点的距离)的类
g.getVertics().get(start).setVivited(true);
for( int i=0;i<g.getVertexCount();i++ )
Distance[i]=-1;
Distance[start] = 0;
while(!PQ.isEmpty()){
v = PQ.DeleteMin().node;
while(g.getAdjUnvisitedVertex(v)!=-1){
w = g.getAdjUnvisitedVertex(v);
g.getVertics().get(w).setVivited(true); //图的对应部分标记为已访问,每个顶点只能被访问一次
int d = Distance[v]+g.Weight(v, w); //计算新的距离
if(Distance[w] == -1){
Distance[w] = d;
PQ.Insert(new NodeWithProority(w, d));
Path[w] = v;
}//if
if(Distance[w] > d){ //如果新的距离比原有的小,需要更新距离
Distance[w] = d;
for(int i=0;i<PQ.count;i++){
if(PQ.array[i].node == w){
PQ.array[i].priority = d;
PQ.Parent(0);
}
}
Path[w] = v;
}//if
}//while
for(int j=0;j<g.getVertexCount();j++) //将访问标记初始化
g.getVertics().get(j).setVivited(false);
}//while
}