Dijkstra单源最短路径算法

    迪科斯彻算法英语:Dijkstra's algorithm)是由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger Wybe Dijkstra)发明的。迪科斯彻算法使用了广度优先搜索算法。算法解决的是有向图中单个源点到其他顶点的最短路径问题。举例来说,如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离,该算法可以用来找到两个城市之间的最短路径。

    该算法的输入包含了一个有权重的有向图 G,以及G中的一个来源顶点S。我们以V 表示G 中所有顶点的集合。每一个图中的,都是两个顶点所形成的有序元素对。(u,v) 表示从顶点 uv 有路径相连。我们以E 所有边的集合,而边的权重则由权重函数 w:E →[0, ∞] 定义。因此,w(u,v) 就是从顶点u 到顶点v 的非负权重(weight)。边的权重可以想像成两个顶点之间的距离。任两点间路径的权重,就是该路径上所有边的权重总和。已知有V 中有顶点st,Dijkstra算法可以找到st 的最低权重路径(例如,最短路径)。这个算法也可以在一个图中,找到从一个顶点s 到任何其他顶点的最短路径。

    

    看上面的一张图,我们模拟这就是现实生活中的几个城市,现在要从0这个城市到3这个城市,可能的线路有0->3,0->1->2->3,0->5->3,0->5->4->3这四条线路可以走。现实生活中,我们总是希望可以尽可能快的到达终点,按照图上的权值,我们可以知道0->5->3这条道路是最短的路径。那么如何知道这条路径是最短的了,这就是Dijkstra可以解决问题的地方了。C代码如下:

    
#include<stdio.h>
#define MAX 100
#define INT_MAX 100000

typedef struct{
    int g[MAX][MAX];  //代表的是图中的每条边
    int n;            //顶点的个数
    int e;            //边的条数
}Graph;

void diskstra(Graph * G,int * least,int * path);  // diskstra实现的核心代码
void findMinPath(Graph * G,int * least,int * path); //找最短路径与最短路径的值

int main(void){
    int i,j;
    int least[MAX] = {0};  //保存每个节点在当前已知路径中的最小权值
    int path[MAX] = {0};   //路径,得到当前路径的上一个节点
    Graph G;
    for(i=0;i<6;i++){
        for(j=0;j<6;j++){
            G.g[i][j] = 0;
        }
    }
    G.n = 6;
    G.e = 8;
    //人为的构造每条边,并且默认0的顶点为起点
    G.g[0][1] = 10;
    G.g[0][5] = 20;
    G.g[0][3] = 98;
    G.g[1][2] = 18;
    G.g[2][3] = 34;
    G.g[5][4] = 22;
    G.g[5][3] = 7;
    G.g[4][3] = 13;
    diskstra(&G,least,path);
    findMinPath(&G,least,path);
    return 0;
}

void diskstra(Graph *G,int * least,int * path){
    int i,j;
    int min,temp;
    int visited[MAX] = {0}; //默认都没有被访问
    //初始化,默认0为起点
    for(i=0;i<G->n;i++){
        if(G->g[0][i] > 0 && i!=0){
            least[i] = G->g[0][i]; 
            path[i] = 0;
        }else{
            least[i] = INT_MAX; //不存在线路,就让其最短距离无穷大
            path[i] = -1;       //把他的前趋设置为-1,代表不存在
        }
    }
    path[0] = 0; //0的前趋为他自己
    least[0] = 0;  //最短路径为0
    visited[0] = 1; //已被访问
 
    for(i=1;i<G->n;i++){
       min = INT_MAX;
       for(j=0;j<G->n;j++){
            if(least[j] < min && visited[j] == 0){
                min = least[j];  //把当前顶点到其他节点的最短距离拿出来
                temp = j;        //获得到其它最短距离的顶点编号
            }
        }

        visited[temp] = 1;  //标示这个顶点已经被访问

        //扩展边的最短路径
        for(j=0;j<G->n;j++){
            if(visited[j] == 0 &&G->g[temp][j] !=0 && min+G->g[temp][j] < least[j]){
                least[j] = min+G->g[temp][j];
                path[j] = temp;
            }
        }
    }
}

void findMinPath(Graph * G,int * least,int * path){
    int stack[MAX] = {0}; //定义一个栈来保存最短路径的线路,类似于dfs
    int top = -1;
    int v = 3;
    int total = least[3];   //求的是到3的最短路径   
    while(v != 0){
        stack[++top] = v;
        v = path[v];
    }
    stack[++top] = v;

    printf("最短线路为:");
    while(top != -1){
        printf("%d ",stack[top--]);
    }
    printf("最短线路的距离为%d",total);

}

    上述代码我们为了给图结合起来是硬编码上述图中的值,实际情况中可能比这要复杂一些。
以下是Dijkstra单源最短路径算法的Python实现: ```python import sys class Graph: def __init__(self, vertices): self.V = vertices self.graph = [[0 for column in range(vertices)] for row in range(vertices)] def printSolution(self, dist): print("Vertex \t Distance from Source") for node in range(self.V): print(node, "\t\t", dist[node]) def minDistance(self, dist, sptSet): min = sys.maxsize for v in range(self.V): if dist[v] < min and sptSet[v] == False: min = dist[v] min_index = v return min_index def dijkstra(self, src): dist = [sys.maxsize] * self.V dist[src] = 0 sptSet = [False] * self.V for cout in range(self.V): u = self.minDistance(dist, sptSet) sptSet[u] = True for v in range(self.V): if self.graph[u][v] > 0 and sptSet[v] == False and dist[v] > dist[u] + self.graph[u][v]: dist[v] = dist[u] + self.graph[u][v] self.printSolution(dist) # 测试 g = Graph(9) g.graph = [[0, 4, 0, 0, 0, 0, 0, 8, 0], [4, 0, 8, 0, 0, 0, 0, 11, 0], [0, 8, 0, 7, 0, 4, 0, 0, 2], [0, 0, 7, 0, 9, 14, 0, 0, 0], [0, 0, 0, 9, 0, 10, 0, 0, 0], [0, 0, 4, 14, 10, 0, 2, 0, 0], [0, 0, 0, 0, 0, 2, 0, 1, 6], [8, 11, 0, 0, 0, 0, 1, 0, 7], [0, 0, 2, 0, 0, 0, 6, 7, 0]] g.dijkstra(0) ``` 输出结果将会是: ``` Vertex Distance from Source 0 0 1 4 2 12 3 19 4 21 5 11 6 9 7 8 8 14 ``` 这个实现中,我们创建了一个Graph类,其中包含了单源最短路径算法Dijkstra的实现。在测试中,我们创建了一个有9个节点的图,并使用Dijkstra算法计算从第0个节点到其他节点的最短路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值