Dijkstra求最短路径

本文详细介绍了Dijkstra算法用于解决单源点最短路径问题的过程和步骤,包括邻接矩阵的使用、顶点选择、路径更新等关键环节,并通过实例展示了算法的具体应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单源点的最短路径问题:给定带权有向图G和源点V,求从V到G中其余各顶点的最短路径

Dijkstra算法描述如下:

(1)用带权的邻接矩阵arcs表示有向图,arcs[i][j]表示弧<vi,vj>上的权值,若<vi,vj>不存在,则置arcs[i][j]=INF。

vis为已找到从v出发的最短路径的终点集合,它的初始状态为空集。那么,从v出发到图上其余各顶点可能到达的最短路径初值为:

D[i]=arcs[Vex(G,v)][i],vi属于V

(2)选择vj,使得D[j]=Min{D[i]|vi属于V-vis},vj就是当前求得的一条从v出发的最短路径的终点。令vis=vis U {j}

(3)修改从v出发到集合V-vis上任一顶点vk可达的最短路径长度。如果D[j]+arcs[j][k]<D[k],则修改D[k]=D[j]+arcs[j][k]

(4)重复操作(2)、(3)工n-1次。由此求得从v到图上其余各顶点的最短路径是依路径长度递增的序列

//Dijkstra:从某个源点到其余各顶点的最短路径
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define N  500
#define INF 0x3f3f3f3f //1061109567 -- 3*(16^7+16^5+16^3+16)+15*(16^6+16^4+16^2+1)
bool vis[N];//顶点是否已经选入S 
int p[N];//前驱顶点 
int dis[N];//最短路径 
typedef struct graph{
    int vexnum;//顶点数
    int edgenum;//边数 
    int arc[N][N];//邻接矩阵 
}Graph;
void CreateGraph(Graph* &);
void Dijkstra(Graph*);
void sp(int,int);//最短路
void CreateGraph(Graph* &G)
{
    int i,v,w; 
    memset(G->arc,INF,sizeof(G->arc));//初始化为INF
    //printf("%d",G->arc[100][100]);
    printf("有向图的顶点数和边数:");
    scanf("%d%d",&G->vexnum,&G->edgenum);
    printf("有向图顶点序号以及关联权值:");
    for(i=0;i<G->edgenum;i++)
    {
        scanf("%d%d",&v,&w);
        scanf("%d",&G->arc[v][w]);
    }
}
void Dijkstra(Graph *G)
{
    int i,v,w,min;
    memset(vis,false,sizeof(vis)); 
    memset(p,0,G->vexnum);//初始时所有终点的前驱顶点都为始点0
    for(i=1;i<G->vexnum;i++)//最短路径初始化为始点到终点的直接路径长度 
        dis[i] = G->arc[0][i];
    for(i=1;i<G->vexnum;i++)//进行G->vexnum-1次循环,按路径递增每次确定一个顶点 
    {
        min = INF;
        for(w=1;w<G->vexnum;w++) 
        {
            if(!vis[w] && dis[w] <= min)//此处取=号是确保输出 路径时能够显示No Path的顶点 
            {
                v = w;//v保存当前最小路径对应的终点
                min = dis[w];
            }
        }
        vis[v] = true;
        sp(v,min);//显示最短路径以及长度 
        for(w=1;w<G->vexnum;w++)//更新当前最短路径以及距离 
        {
            if(!vis[w] && min + G->arc[v][w] < dis[w])
            {
                dis[w] = min + G->arc[v][w];
                p[w] = v;
            }
        }
    }
}
void sp(int v,int pow)
{
    if(pow == INF)
    {
        printf("V0--->V%d:No Path\n",v); 
    }
    else{
        printf("V0-->V%d最短路径长度为:%d,路径如下:\n",v,pow);
        while(v)//从后往前打印,到始点0结束 
        {
            printf("V%d<-",v);
            v = p[v];
        }
        printf("V0\n");
    }
}
int main()
{
    Graph *G = (Graph *)malloc(sizeof(Graph));
    CreateGraph(G);
    Dijkstra(G);
    return 0;
}
 // 6 8
// 0 2 10
// 0 4 30
// 0 5 100
// 4 5 60
// 4 3 20
// 3 5 10
// 2 3 50
// 1 2 5

 

转载于:https://www.cnblogs.com/520xiuge/p/5405570.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值