单源最短路经(Dijkstra算法的详解)

本文介绍了一种使用迪杰斯特拉算法实现单源最短路径的C语言程序设计方法。该程序通过定义结构体来表示图的边,并利用数组记录顶点之间的距离和访问状态,实现了对加权图中任意顶点到其它所有顶点的最短路径计算。

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

#include<stdio.h>
#include<string.h>
int n,m;// n 顶点数  m  边数
int visit[1001];//visit[Vj] = 1 表示Vj 到源点已是最短的。
int countt;// 记录边数
int head[1001];// 头结点 存的值是 边所在的位置 head[]的下标为头结点
int dist[1001];// 源点到各顶点的最短距离
#define INF 999999; // INF  为 无穷大
typedef struct EDGE{
    int v,w;// w 为边的权值,v 为 弧所指向的顶点
    int next;// next 为 边所指向的下一条边所在的位置
}EDGE;
EDGE edge[2001]; // edge[] 下标为边所在的位置
void addedge(int u,int v,int w){
    edge[countt].v = v;
    edge[countt].w = w;
    edge[countt].next = head[u];
    head[u] = countt++;
}
/** 迪杰斯特拉的思想: 由上述性质可知,如果存在一条从i到j的最短路径(Vi.....Vk,Vj),
Vk是Vj前面的一顶点。那么(Vi...Vk)也必定是从i到k的最短路径。为了求出最短路径,
Dijkstra就提出了以最短路径长度递增,逐次生成最短路径的算法。譬如对于源顶点V0,
首先选择其直接相邻的顶点中长度最短的顶点Vi,那么当前已知可得从V0到达Vj顶点的
最短距离dist[j]=min{dist[j],dist[i]+matrix[i][j]}。根据这种思路,
假设存在G=<V,E>,源顶点为V0,S={V0},dist[i]记录V0到i的最短距离,
path[i]记录从V0到i路径上的i前面的一个顶点。
1.从V-S中选择使dist[i]值最小的顶点i,将i加入到S中;
2.更新与i直接相邻顶点的dist值。(dist[j]=min{dist[j],dist[i]+matrix[i][j]})
3.知道S集合=V集合,停止。
**/
// 单源最短路经
void Dijkstra(int start){
     for(int i = 1;i <= n;i++){
            dist[i] = INF;// 初始化源点到各顶点的距离为无穷大
        }
        for(int eg = head[start];eg!=-1;eg = edge[eg].next){
                int v = edge[eg].v;
                dist[v] = edge[eg].w;// 若 从源点到 Vj 上有弧,则dist[Vj] = 弧上的权值
        }
        visit[start] = 1;// visit[] = 1 的点表示在 S 集合中的店
        dist[start] = 0;// 源点到源点的距离为 0
        int minNode;
     for(int i = 1;i <= n-1;i++){ // 遍历n - 1  次; 找到其余n-1 个点到源点的最短距离
       int  minn = INF;
        for(int j = 1;j <= n;j++){// 找到dist[] 里的最小值,并且是在V-S集合中的点
            if(!visit[j]&&minn > dist[j]) {minn = dist[j];minNode = j;}
        }
        visit[minNode] = 1; //将找到的点纳入S集合中
        for(int eg = head[minNode];eg!=-1;eg = edge[eg].next){
            int p = edge[eg].v;
            if(!visit[p]&&(minn+edge[eg].w)<dist[p]) {//更新dist当前最短路径
                dist[p]  = minn+edge[eg].w;
            }
        }
     }

}
int main(){
    printf("先输入顶点数,后边数:\n");
    while(scanf("%d%d",&n,&m)){
        countt = 0;
        for(int i = 1;i <= n;i++){
            head[i] = -1;// 初始化各顶点 所指向的边的位置为-1
        }
        int u,v,w;// 相邻的u ,v 顶点  w 为边的权值
        for(int i = 1;i <= m;i++){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
        }
        int start;// 源点
        printf("输入源点:");
        scanf("%d",&start);
        memset(visit,0,sizeof(visit));
        Dijkstra(start);
        for(int i = 1;i <= n;i++){
            printf("%d点到%d的距离为%d\n",start,i,dist[i]);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值