最短路径问题-Dijkstra算法

算法介绍

迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。

它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

基本思想

通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算)。

此外,引进两个集合S和U。S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离)。

初始时,S中只有起点s;U中是除s之外的顶点,并且U中顶点的路径是"起点s到该顶点的路径"。然后,从U中找出路径最短的顶点,并将其加入到S中;接
着,更新U中的顶点和顶点对应的路径。 然后,再从U中找出路径最短的顶点,并将其加入到S中;接着,更新U中的顶点和顶点对应的路径。 ...
重复该操作,直到遍历完所有顶点。

操作步骤

(1) 初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点的距离为"起点s到该顶点的距离"[例如,U中顶点v的距离为(s,v)的长度,然后s和v不相邻,则v的距离为∞]。

(2) 从U中选出"距离最短的顶点k",并将顶点k加入到S中;同时,从U中移除顶点k。

(3) 更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离,是由于上一步中确定了k是求出最短路径的顶点,从而可以利用k来更新其它顶点的距离;例如,(s,v)的距离可能大于(s,k)+(k,v)的距离。

(4) 重复步骤(2)和(3),直到遍历完所有顶点。

 时间复杂度:o(n^2).

求v0到v8的最短路径:

代码如下:

#include <stdio.h>

#define MAXVEX 9
#define MAXEDGES 16
#define INFINITE 60000

//定义图的类型
typedef struct {
    int vexs[MAXVEX];//保存顶点名称
    int arc[MAXVEX][MAXVEX];//邻接矩阵
    int numVertexs,numEdges;
}MGraph;

typedef int Patharc[MAXVEX];    //存储最短路径的情况下,每个顶点的上一个顶点
typedef int ShortPathTable[MAXVEX];    //存储v0到各个顶点最短路径的长度

//构建图
void CreateMGraph(MGraph * G){
    int i,j;
    G->numEdges=16;
    G->numVertexs=9;
    //给每个顶点命名
    for(i=0; i<G->numVertexs; i++){
        G->vexs[i]=i;
    }

    for(i=0; i<G->numVertexs; i++){
        for(j=0; j<G->numVertexs; j++){
            if(i==j){
                G->arc[i][j]=0;
            }else{
                G->arc[i][j]=INFINITE;
            }
        }
    }

    G->arc[0][1]=1;
    G->arc[0][2]=5;
    G->arc[1][2]=3;
    G->arc[1][3]=7;
    G->arc[1][4]=5; 

    G->arc[2][4]=1;
    G->arc[2][5]=7;
    G->arc[3][4]=2;
    G->arc[3][6]=3;
    G->arc[4][5]=3;

    G->arc[4][6]=6;
    G->arc[4][7]=9;
    G->arc[5][7]=5;
    G->arc[6][7]=2;
    G->arc[6][8]=7;

    G->arc[7][8]=4;

    for(i=0;i<G->numVertexs; i++){
        for(j=0; j<i; j++){
            G->arc[i][j]=G->arc[j][i];
        }
    }
}

/*  Dijkstra算法,求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度D[v] */
/*  P[v]的值为前驱顶点下标,D[v]表示v0到v的最短路径长度和 */
void ShortestPath_Dijkstra(MGraph G, int v0, Patharc *P, ShortPathTable *D){
    int i,j,k,w;
    int final[MAXVEX];//如果找到到某顶点的最短路径,就标记1,初始为-1

    for(i=0; i<G.numVertexs; i++){
        (*P)[i]=0;//初始P[]为0
        final[i]=-1;
        (*D)[i]=G.arc[0][i];//初始化顶点0到其他顶点的长度
    }

    final[0]=1;//到0的最短路径已经找到了,就是本身

    for(i=1; i<G.numVertexs; i++){//以下的1,2,3,步骤,每进行一次会确定一个不同的顶点,
        //使得v0到该顶点的距离最短,如此循环G.numVertexs-1次,可以找到v0到其余所有顶点的最短路径

        //1.找v0到各个顶点最短的路径
        int min=INFINITE;
        for(j=1; j<G.numVertexs; j++){
            if(final[j]!=1 && (*D)[j] < min){
                min=(*D)[j];
                k=j;
            }
        }

        //2.顶点k的最短路径已经找到,就是min(找到一个做一次标记)
        final[k]=1;

        //3. 如果经过v顶点的路径比现在这条路径的长度短的话,更新v0到该顶点的距离,否则不进行任何操作
        for(w=1; w<G.numVertexs; w++){
            if(final[w]!=1 && min+G.arc[k][w] < (*D)[w]){
                /*  说明找到了更短的路径,修改D[w]和P[w] */
                (*D)[w]=min+G.arc[k][w];
                (*P)[w]=k;
            }
        }

    }
}

int main(){

MGraph G;
int i,j,t,v0=0;
Patharc P;
ShortPathTable D;

CreateMGraph(&G);

ShortestPath_Dijkstra(G, v0, &P, &D);

    //打印
    for(j=1; j<G.numVertexs; j++){

        printf("v%d-->v%d的最短路径长度为%d\n",v0,j,D[j]);

        t=j;
        printf("最短路径倒叙为v%d-->",t);
            while(P[t]!=0){
            printf("v%d-->",P[t]);
            t=P[t];
            }
        printf("v%d\n\n",P[t]);
    }
return 0;
}

结果:

时间: 2024-08-05 15:51:02

最短路径问题-Dijkstra算法的相关文章

最短路径之Dijkstra算法

Dijkstra算法: 首先,引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点vi的的长度:如D[3]=2表示从始点v到终点3的路径相对最小长度为2.这里强调相对就是说在算法过程中D的值是在不断逼近最终结果但在过程中不一定就等于长度.它的初始状态为:若从v到vi有弧,则D为弧上的权值:否则置D为∞.显然,长度为 D[j]=Min{D | vi∈V} 的路径就是从v出发的长度最短的一条.此路径为(v,vj). 那么,下一条长度次短的是哪一条呢?假设该次短路径的终点是vk,

图的单源最短路径:Dijkstra算法实现

本文介绍的是图的非负权值的单源最短路径问题.问题的提出是,对于有权图D,t提供源点v,要找到从v到其他所有点的最短路径,即单源最短路径问题,在本文中,解决这一问题,是普遍比较熟悉的Dijkstra算法. 算法核心思想参见维基.简而言之,设集合S存放已经求出了最短路径的点.初始状态S中只有一个点v0,之后每求得v0到vn的最短路径,就会更新v0到所有vn邻接的点的一致的最短路径(不一定是最终的最短路径),如此重复,每次会确定v0到一个点的最短路径,确定好的点加入S中,直至所有点进入S结束.在本文中

单源最短路径(dijkstra算法)php实现

做一个医学项目,其中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路如下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么(Vi...Vk)也必定是从i到k的最短路径.Dijkstra是以最短路径长度递增,逐次生成最短路径的算法.例如:对于源顶点V0,首先选择其直接相邻的顶点中长度最短的顶点Vi,那么当前已知可得从V0到达Vj顶点的最短距离dist[j]=min{dist[j],dist[i]+cost[i][j]}.假设G

hdu 2680 最短路径(dijkstra算法+多源最短路径单源化求最小值)

Choose the best route Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7062    Accepted Submission(s): 2301 Problem Description One day , Kiki wants to visit one of her friends. As she is liable

ACM: HDU 3790 最短路径问题-Dijkstra算法

HDU 3790 最短路径问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Input 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p.最后一行是

Java数据结构 最短路径解法Dijkstra算法

本文为博主原创文章,未经博主允许不得转载! 1.1.定义概览Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径.(

单源点最短路径的Dijkstra算法

在带权图(网)里,点A到点B所有路径中边的权值之和为最短的那一条路径,称为A,B两点之间的最短路径;并称路径上的第一个顶点为源点(Source),最后一个顶点为终点(Destination).在无权图中,最短路径则是两点之间经历的边数最少的路径.实际上,只要把无权图上的每条边都看成是权值为1的边,那么无权图和带权图的最短路径是一致的. 给定一个带权有向图G=(V,E),指定图G中的某一个顶点的V为源点,求出从V到其他各顶点之间的最短路径,这个问题称为单源点最短路径问题. 迪杰斯特拉(Dijkst

最短路径问题——dijkstra算法

仅谈谈个人对dijkstra的理解,dijkstra算法是基于邻接表实现的,用于处理单源最短路径问题(顺便再提一下,处理单源最短路径问题的还有bellman算法).开辟一个结构体,其变量为边的终点和边权,这时候还需要一个这个结构体类型的数组,数组的下标则为边的始点,我们都知道在图中,一个始点连出去的可能不止一条边,这样的话就类似用到一个二维数组了,我们在arr[][]的第一维存放的是边的始点,第二维则是这个始点对应的不同终点及其权值,学过邻接表的人应该就能看出来这就是一个邻接表了呗! 而对于邻接

python数据结构与算法——图的最短路径(Dijkstra算法)

1 # Dijkstra算法——通过边实现松弛 2 # 指定一个点到其他各顶点的路径——单源最短路径 3 4 # 初始化图参数 5 G = {1:{1:0, 2:1, 3:12}, 6 2:{2:0, 3:9, 4:3}, 7 3:{3:0, 5:5}, 8 4:{3:4, 4:0, 5:13, 6:15}, 9 5:{5:0, 6:4}, 10 6:{6:0}} 11 12 13 # 每次找到离源点最近的一个顶点,然后以该顶点为重心进行扩展 14 # 最终的到源点到其余所有点的最短路径 15