最短路径

最短路问题的抽象.

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

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

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

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值