单源最短路径 dijkstra算法实现

  本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图,并且连通,有向图,不连通图的做法类似。

算法简述:

  1. 首先确定“单源”的源,假设是第0个顶点。
  2. 维护三个数组dist[], color[], path[],设其下标分别为0…i…n-1:

      dist[] 表示源点到顶点i的最短距离,在初始化时,如果源点到顶点i有路径,则初始化为路径的权重,否则初始化为INT_MAX;

      color[] 数组其实表示两个集合,即color[i]值为1的集合表示已经确定最短路径的点的集合,color[i]值为0表示没有确定最短路径的点的集合。初始化为将源点的color设置为1,其余点设置为0;

      path[]数组存储到顶点i的路径,如果path[i]=3,path[3]=2,paht[2]=0,则这条最短路径是0->2->3->i,与数组给出的顺序是逆序。

  3. 依次从dist[]数组中选一个最小的dist值,假设顶点的坐标为index,这个dist值即为最终确定的最短距离的点,更新这个点的color值为1,下面一个操作是dijkstra算法的重点,也只有这么一个重点操作,即:在没有确定最短距离的集合中(即color值为0的点的集合),如果源点到index的距离,加上index到这些点的距离小于原来的dist值,则更新dist值,同时更新path值。
  4. 重复第3个操作,直到color值为0的集合为空。

下面给出c语言实现代码,方法都出了注释,这里不再说明, 如果不足之处请提出(使用的默认的图如下):

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>

int n;
int source = 0;     //求从第0个节点到其他节点的最短路径
int* dist;
int* path;
int* color;     //颜色为1说明已经找到最短路径,为-1说明没找到最短路径

//获得默认的图,即上图所示,使用邻接矩阵表示
int** get_graph(){
    int** matrix;
    int i,j;
    int start,end,weight;

    printf("input vertex num:\n");
    scanf("%d",&n);

    matrix = (int**)malloc(sizeof(int*)*n);

    for(i=0;i<n;i++){
        matrix[i] = (int*)malloc(sizeof(int)*n);
        for(j=0;j<n;j++){
            if(i!=j)
                matrix[i][j] = INT_MAX;
            else
                matrix[i][j] = 0;
        }
    }

    printf("input start end weight, stop by -1\n");

    for(;;){
        scanf("%d",&start);
        if(start==-1){
            break;
        }
        scanf("%d %d",&end,&weight);
        matrix[start][end] = weight;
        matrix[end][start] = weight;
    }
    return matrix;
}

//使用迪杰斯特拉算法求单源最短路径
void single_source_shortest_path(int** matrix,int source){

    int i,j,index,min;

    dist = (int*)malloc(sizeof(int)*n);
    color = (int*)malloc(sizeof(int)*n);
    path = (int*)malloc(sizeof(int)*n);

    //初始化最短路径:
    //直接相连的初始化为权重,不直接相连的初始化为INT_MAX
    for(i=0;i<n;i++){
        dist[i] = matrix[source][i];
        color[i] = 0;
        if(i!=source && dist[i]!=INT_MAX){
            path[i] = source;
        }else{
            path[i] = -1;
        }
    }

    color[source] = 1;
    path[source] = 0;

    //找一个从源点到其他节点最短的路径
    for(j=0;j<n;j++){
        min = INT_MAX;
        index = -1;
        for(i=0;i<n;i++){
            if(!color[i] && dist[i]<min){
                index = i;
                min = dist[i];
            }
        }

        if(index==-1){  //所有定点的最终距离都确定
            break;
        }

        color[index] = 1;   //标记为已经确定最短距离的定点

        //接下来更新到每个未确定最短距离的定点的距离
        //如果源点到刚刚添加的节点的最短距离+刚刚添加的节点的距离到未确定最短距离的定点的距离 < 源最短距离,则更新
        for(i=0;i<n;i++){
            if(!color[i] && matrix[index][i]!=INT_MAX && dist[index]+matrix[index][i]<dist[i]){
                 dist[i] = dist[index]+matrix[index][i];
                 path[i] = index;
            }
        }
    }
}

int main(){

    int** matrix = get_graph();
    int i,t;

    single_source_shortest_path(matrix,source);

    printf("\n");
    for(i=0;i<n;i++){
        printf("%d: %d,and the path is(inverse order): %d ",i,dist[i],i);
        t = path[i];
        while(1){
            printf(" %d ",t);
            if(t==0){
                break;
            }
            t = path[t];
        }
        printf("\n");
    }

    printf("\n");
    return EXIT_SUCCESS;
}

运行结果如下:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 18:30:58

单源最短路径 dijkstra算法实现的相关文章

数据结构:单源最短路径--Dijkstra算法

Dijkstra算法 单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. Dijkstra算法 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合.假设V0是源点,则初始 S={V

单源最短路径Dijkstra算法

1.单源最短路径 函数:返回还未被收录顶点中dist最小者 1 Vertex FindMinDist(MGraph Graph, int dist[], int collected[]) 2 { 3 /*返回未被收录顶点中dist最小者*/ 4 Vertex MinV, V; 5 int MinDist = INFINITY; 6 7 8 for (V = 0; V < Graph->Nv; ++V) 9 { 10 if (collected[V] == false && di

(转)图算法单源最短路径Dijkstra算法(邻接表/邻接矩阵+优先队列STL)

一.前言 最短路径算法,顾名思义就是求解某点到某点的最短的距离.消耗.费用等等,有各种各样的描述,在地图上看,可以说是图上一个地点到达另外一个地点的最短的距离.比方说,我们把地图上的每一个城市想象成一个点,从一个城市到另一个城市的花费是不一样的.现在我们要从上海去往北京,需要考虑的是找到一条路线,使得从上海到北京的花费最小.有人可能首先会想到,飞机直达啊,这当然是时间消耗最小的方法,但是考虑到费用的高昂,这条线路甚至还不如上海到北京的高铁可取.更有甚者,假设国家开通了从上海到西藏,再从西藏到兰州

单源最短路径——Dijkstra算法学习

每次都以为自己理解了Dijkstra这个算法,但是过没多久又忘记了,这应该是第4.5次重温这个算法了. 这次是看的胡鹏的<地理信息系统>,看完之后突然意识到用数学公式表示算法流程是如此的好理解,堪称完美. 内容摘抄如下: 网络中的最短路径是一条简单路径,即是一条不与自身相交的路径,最短路径搜索的依据:若从S点到T点有一条最短路径,则该路径上的任何点到S的距离都是最短的. Dijkstra算法搜索步骤: 1.对起始点作标记S,且对所有顶点令D(X)=∞,Y=S: 2.对所有未做标记的点按以下公式

单源最短路径Dijkstra、BellmanFord、SPFA【模板】

Dijkstra算法: 将所有点分为两个集合.如果源点s到u的最短路径已经确定,点u就属于集合Va,否则属于集合Vb. 1.将源点s到图中各点的直接距离当做初始值记录为s到各点的最短距离,不能到达的记为INF.S到S距离为0. 2.在集合Vb中的点中找一个点u,使得源点s到该点u路径长度最短,将u从Vb中除去,加到V1中.这时候求出了当前S到u的最短路径. 3.把新确定的点u更新s到集合Vb中每一个点v的距离,如果s到u的距离加上u到v的直接距离小于当前s到v的距离,则表示新找到的最短路径长度比

单源最短路问题 dijkstra算法 总结

Dijkstra(迪杰斯特拉)算法,用于计算一个节点到其他所有节点的最短路径.要注意的是这个算法中路径的权值不能有负边,如果有负边的话要运用bellman ford算法. 学习了一下dijkstra算法,感觉跟最小生成树的Prim算法有点类似.感觉dijkstra也是一个贪心的策略,用集合S表示的是已经找出最小路径的点,用dis[]来表示每个点当前距离源点的最短距离.再用一个数组来存储两点之间的距离,对于没有直接相连的两点就将值赋为INF. 1.一开始的时候,集合S中只有源点. 2.选取尚未被找

单源最短路径Dijkstra和优先级算法

百度百科:迪杰斯特拉算法. 代码实现如下: import java.util.Comparator; import java.util.PriorityQueue; import java.util.Scanner; class Node { int x; int value; } public class Main { static int N,M,cnt; static final int MAX = 105; static final int INF = 1000009; static N

单源最短路径——Floyd算法

正如我们所知道的,Floyd算法用于求最短路径.Floyd算法可以说是Warshall算法的扩展,三个for循环就可以解决问题,所以它的时间复杂度为O(n^3). Floyd算法的基本思想如下:从任意节点A到任意节点B的最短路径不外乎2种可能,1是直接从A到B,2是从A经过若干个节点X到B.所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离,对于每一个节点X,我们检查Dis(AX) + Dis(XB) < Dis(AB)是否成立,如果成立,证明从A到X再到B的路径比A直接到B的路径短,

单源最短路径(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