最短路径

来源:互联网 发布:linux执行shell脚本 编辑:程序博客网 时间:2024/05/29 04:22

最短路问题的抽象.

在网络中,求两个不同顶点之间的所有路径中,边的权值之和最小的那一条路径.
这条路径就是两点之间的最短路径.
第一个顶点为源点.
最后一个顶点为终点.

单源最短路问题:从某个固定点出发,求到其他所有点的最短路径问题.
(有向)无权图
(有向)有权图
多源最短路问题:求任意两个顶点之间的最短路径.

按照递增(非递减)的顺序找到各个顶点的最短路
无权图的单源最短路问题:

dist[W] = S到W的最短距离void Unweighted(Vertex S){    Enqueue(S,Q);    while(!IsEmpty(Q)){        V = Dequeue(Q);        for(V的每个邻接点W)        if(dist[W] == -1){            dist[W] = dist[V] + 1;            path[W] = V;            Enqueue(W,Q);         }    }}

有权图的单源最短路问题:
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等。注意该算法要求图中不存在负权边。

算法描述:
算法思想:设G=(V,E)是一个带权有向图,把图中顶点集合V分成两组,第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了),第二组为其余未确定最短路径的顶点集合(用U表示),按最短路径长度的递增次序依次把第二组的顶点加入S中。在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度。此外,每个顶点对应一个距离,S中的顶点的距离就是从v到此顶点的最短路径长度,U中的顶点的距离,是从v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度

代码实现

//邻接矩阵存储 - 有权图的单源最短路算法 Vertex FindMinDist(MGraph Graph,int dist[],int collected[]){    //返回未被收录顶点中dist最小者     Vertex MinV,V;    int MinDist = INFINITY;    for(V=0;V<Graph->Nv;V++)    {        if(collected[V] == false && dist[V] < MinDist){            //若未被收录,且dist[V]更新             MinDist = dist[V];//更新最小距离             MinV = V;//更新对应顶点         }    }    if(MinDist < INFINITY)//若找到最小dist         return MinV;//返回对应顶点的下标     else return ERROR;}bool Dijkstra(MGraph Graph,int dist[],int path[],Vertex S){    int collected[MaxVertexNum];    Vertex V,W;    //初始化:此处默认邻接矩阵中不存在的边 INFINITY    for(V=0;V<Graph->NV;V++)    {        dist[V] = Graph->G[S][V];        path[V] = -1;        collected[V] = false;    }    //先将起点收入集合    dist[S] = 0;    collected[S] = true;    while(1){        // V = 未被收录顶点中dist最小者        V = FindMinDist(Graph,dist,collected);        if(V == ERROR)            break;//算法结束         collected[V] = true;//收录V        for(W=0;W<Graph->Nv;W++)//对图每个顶点W         {             //W是V的邻接点并且未被收录             if(collected[W]=false&&Graph->G[V][W]<INFINITY){                //存在负边                 if(Graph->G[V][W] < 0){                    return false;//不能正确解决返回错误标记                 }                //如果收录的结点V使得dist[W]变小                if(dist[V] + Graph->G[V][W] < dist[W]){                    dist[W] = dist[W] + Graph->G[V][W];                    path[W] = V;//更新S到W的路径                  }             }        }    }    return true;}

多源最短路算法:
方法一:直接将单源最短路算法调用|V|遍 (对于稀疏图使用)

方法二:Floyd算法

bool Floyd(MGraph Graph,WeightType D[][MaxVertexNum],Vertex path[][MaxVertexNum]){    Vertex i,j,k;    //初始化    for(i=0;i<Graph->Nv;i++)        for(j=0;j<Graph->Nv;j++){            D[i][j] = Graph->G[i][j];            path[i][j];        }    for(k=0;K<Graph->Nv;k++)        for(i=0;i<Graph->Nv;i++)            for(j=0;j<Graph->Nv;j++)                if(D[i][k] + D[k][j] < D[i][j]){                    if(i==j&&D[i][j])//如果发现负值圈                        return false;                    path[i][j] = k;                 }    return false;    }
0 0
原创粉丝点击