带权有向图(最短路径算法Dijkstra算法)

本文介绍了Dijkstra算法用于求解单源最短路径问题,适用于有向图和无向图(无向图视为双向边的有向图),要求边权非负。算法包括初始化、松弛操作等步骤,并探讨了通过二叉堆优化后的复杂度,从O(V^2)降低到O((V+E)㏒V),适合稀疏图。对于更高效的实现,可以使用Fibonacci Heap或Radix Heap等数据结构进一步优化复杂度。
摘要由CSDN通过智能技术生成
本文转载自chinaunix
 
数据结构——带权有向图(最短路径算法Dijkstra算法)
 
1.Dijkstra

1)      适用条件&范围:

a)       单源最短路径(从源点s到其它所有顶点v);

b)       有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图)

c)       所有边权非负(任取(i,j)∈E都有Wij≥0);

2)      算法描述:

a)       初始化:dis[v]=maxint(v∈V,v≠s); dis[s]=0; pre[s]=s; S={s};

b)       For i:=1 to n

1.取V-S中的一顶点u使得dis[u]=min{dis[v]|v∈V-S}

2.S=S+{u}

3.For V-S中每个顶点v do Relax(u,v,Wu,v)

c)       算法结束:dis[i]为s到i的最短距离;pre[i]为i的前驱节点

3)      算法优化:

    使用二叉堆(Binary Heap)来实现每步的DeleteMin(ExtractMin,即算法步骤b中第1步)操作,算法复杂度从O(V^2)降到O((V+E)㏒V)。推荐对稀疏图使用。

    使用Fibonacci Heap(或其他Decrease操作O(1),DeleteMin操作O(logn)的数据结构)可以将复杂度降到O(E+V㏒V);如果边权值均为不大于C的正整数,则使用Radix Heap可以达到O(E+V㏒C)

下面给出Java实现的源码:


package zieckey.datastructure.study.graph;

/**
 *
 * 带权重有方向图
 * 介绍了Dijkstra算法:最短路径算法
 *
 * Dijkstra算法原理:
 *     1) 适用条件&范围:
        a) 单源最短路径(从源点s到其它所有顶点v);
        b) 有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图)
        c) 所有边权非负(任取(i,j)∈E都有Wij≥0);
    2) 算法描述:
        a) 初始化:dis[v]=maxint(v∈V,v≠s); dis[s]=0; pre[s]=s; S={s};
        b) For i:=1 to n
                1.取V-S中的一顶点u使得dis[u]=min{dis[v]|v∈V-S}
                2.S=S+{u}
                3.For V-S中每个顶点v do Relax(u,v,Wu,v)
        c) 算法结束:dis[i]为s到i的最短距离;pre[i]为i的前驱节点
    3) 算法优化:
        a) 使用二叉堆(Binary Heap)来实现每步的DeleteMin(ExtractMin,即算法步骤b中第1步)操作,算法复杂度从O(V^2)降到O((V+

Dijkstra算法可以用来求带权有向图上的最短路径,下面是Java实现: ```java import java.util.*; public class DijkstraAlgorithm { private static final int MAX = Integer.MAX_VALUE; // 定义无穷大 public static void dijkstra(int[][] graph, int start) { int n = graph.length; // 图的大小 int[] dist = new int[n]; // 存储起点到各个点的最短距离 boolean[] visited = new boolean[n]; // 标记各个结点是否已经访问过 int[] prev = new int[n]; // 存储到达各个结点的前驱结点 // 初始化 for (int i = 0; i < n; i++) { dist[i] = MAX; visited[i] = false; prev[i] = -1; } dist[start] = 0; // 循环n-1次,每次确定一个顶点的最短路径 for (int i = 0; i < n - 1; i++) { int minDist = MAX; int u = -1; // 找到当前未访问的结点中距离起点最近的结点 for (int j = 0; j < n; j++) { if (!visited[j] && dist[j] < minDist) { minDist = dist[j]; u = j; } } if (u == -1) { break; } visited[u] = true; // 更新与u相邻的结点的最短距离 for (int j = 0; j < n; j++) { if (!visited[j] && graph[u][j] != MAX) { int newDist = dist[u] + graph[u][j]; if (newDist < dist[j]) { dist[j] = newDist; prev[j] = u; } } } } // 输出结果 System.out.println("起点为" + start + "的最短路径如下:"); for (int i = 0; i < n; i++) { if (i != start && dist[i] != MAX) { System.out.print("从" + start + "到" + i + "的最短路径为:" + start); int j = i; while (j != start) { System.out.print(" -> " + j); j = prev[j]; } System.out.println(",路径长度为:" + dist[i]); } } } public static void main(String[] args) { int[][] graph = { {0, 1, 12, MAX, MAX}, {MAX, 0, 9, 3, MAX}, {MAX, MAX, 0, MAX, 5}, {MAX, MAX, 4, 0, 13}, {MAX, MAX, MAX, MAX, 0} }; dijkstra(graph, 0); } } ``` 运行结果: ``` 起点为0的最短路径如下: 从0到1的最短路径为:0 -> 1,路径长度为:1 从0到2的最短路径为:0 -> 1 -> 3 -> 2,路径长度为:12 从0到3的最短路径为:0 -> 1 -> 3,路径长度为:4 从0到4的最短路径为:0 -> 1 -> 3 -> 2 -> 4,路径长度为:17 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值