Dijkstra算法以及c语言代码

1.算法简介

Dijkstra算法又称标号法,用来寻找带权途中的最短路径问题
是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是从起始点开始,采用贪心算法的策略,每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。

2.原理

1.找到起始点

任选一个点作为起始点

2.计算起始点第一步

计算起始点第一步能到达的点的距离,并选择这些距离中的最小距离作为到达的点作为中介点

3.以中介点往下计算

以中介点作为点往下进行计算,计算以这个中介点到达下一个点的距离,若计算出的距离小于上次计算的距离,者进行替换,包括上次的步骤路径一起进行替换。若大于上次的距离,则不需要进行替换,并寻找这次起始点经各路径到达每个点的距离中的最短距离

4.重复以上步骤

重复寻找,知道找到全部最短距离为止

2.实际操作

在这里插入图片描述

在这里插入图片描述

1,选择初始点为点1

2.计算初始点到一步就能到达的点

3.比较:

在这里插入图片描述
即比较这一列

4.以得到的红色结果继续寻找并比较

寻找到的结果继续比较
在这里插入图片描述
即比较得到的结果与上次的结果,就是比较每一行,并进行替换
比较之后再次比较每列,得到该次的结果

5.重复以上步骤直到找到所有结果

在这里插入图片描述

3.总结

通俗而言就是只有两个步骤,就是比较和替换,先比较列,在比较行,找到最小值。每次如此,进行寻找。直到找到全部为止

4.c语言代码

以矩阵输入

#include <stdio.h>
#define INF 1000 //将该值当做等价无穷小
#define Max 50
int main()
{
	int jz[Max][Max];      //Max为最大顶点数
	int min1[Max];             //min1[i]为源点到顶点i的最短距离
	int done[Max];            //done[i]标记顶点i的最短路径是否已求出 done[i] == 1表示已求出
	int jd[Max];            //jd[i]表示 起始点通过jd[i]这个点到达i这个点最短路径 <v1,v2,v3>中jd[3]=2
    int n,q = 0; 		//q是已求出最短路径的顶点数目
    
    printf("请输入节点个数:");
    scanf("%d", &n);
	printf("\n请输入矩阵:\n");    
    int lj[n];  //lj表示路径  
    for (int i = 0; i < n; i++)    //矩阵的输入
    {        
        for (int j = 0; j < n; j++)        
        {            
            scanf("%d",&jz[i][j]);        
        }    
    } 
	
	   
	done[0] = 1;    		//起始点不可求到起始点的最短距离,相当于已经求出
	jd[0] = 0;       
	for (int i = 1; i < n; i++)    //初始化
	{        
	    min1[i] = jz[0][i];        //将起始点到各点的距离录入
	    jd[i] = 0;          //
	}    
	q++;                       //上面求出一个最短距离点,故此加 1
	while (q < n)              //n个节点求n-1次
	{        
	    int min = INF, a;          //初始化值,以供每次循环使用
	    for (int i = 1; i < n; i++)        
	    {             
	        if (done[i] == 0 && min > min1[i])         //找到距离源点最短的顶点a
	        {                
	            min = min1[i];                       //这个循环是求表中每个列的最小值
	            a = i;            
	        }
	    }        
	    done[a] = 1;        						//表中每列最小值即为到对应点的最小值
	    q++;        							//求出最小值后,加一
	    
	    //实际上是先算下面这一个循环,但第一个循环在初始化的时候就相当与进行了
	    for (int i = 1; i < n; i++)        
	    {            
	        if (done[i] == 0 && min1[a] + jz[a][i] < min1[i])  //计算表中下一列的各个数值,若比上次的小,则更新
	        {                
	            min1[i] = min1[a] + jz[a][i];    //替换成更小的值
	            jd[i] = a;                //表示到达 i节点的前一个点,每次路径比前一个小时,更新
	        }        
	    }    
	} 
	
	   
    printf("\n\n");    
    for (int i = 1; i < n; i++)    
    {        
        if (min1[i] == INF)        
        {            
            printf("点 1 到点 %d 没有最短路径\n", i);
        }        
        else
        {
    	    printf("点 1 到点 %d 有长为 %d 的最短路径:",i+1,min1[i]);
    	    int b = i, c= 0;            //初始化值,用于每次循环
            lj[c] = b;            		//倒序存放,最后一个数字存放起始点
            //找路径
            while (1)            
            {                
                lj[c + 1] = jd[lj[c]];  //每向后一位找到在最短路径上该点的前一位,i点的前一位为jd[i]
                if (lj[c + 1] == 0)     //每次前一位录入路径中欧判断,起始点是0,所与当向后找到最后一位是0,结束
				{                    
                    break;
				}                
                c++;            		//每次循环向后一位,进行加一
            }
			//打印输出
            for (int j = c + 1; j > 0; j--)
            {                
                printf("%d->", lj[j]+1);
            }            
            printf("%d\n", lj[0]+1);        
        }    
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值