c课设报告《基于Dijkstra算法的最短路径问题求解》
- 格式:docx
- 大小:250.41 KB
- 文档页数:17
Dijkstra算法原理详细讲解
Dijkstra算法是图论中的一种贪心算法,用于求解最短路径问题。
该算法的贪心策略是:每次选择当前距离起点最近的节点作为中间节点,并更新起点到其它节点的距离。
通过不断选择距离起点最近的节点,并逐步更新起点到各个节点的距离,最终得到起点到终点的最短路径。
Dijkstra算法的具体实现包括以下几个步骤:
1. 初始化:将起点到各个节点的距离记为无穷大或者一个较大的值,将起点到自己的距离记为0。
2. 选择当前距离起点最近的节点作为中间节点。
这个过程可以通过维护一个距离起点最近的节点集合来实现,初始时集合中只包含起点。
3. 更新起点到与中间节点相邻的节点的距离,即对于每个与中间节点相邻的节点,如果从起点到中间节点的距离加上中间节点到该节点的距离小于起点到该节点的距离,则更新起点到该节点的距离为从起点到中间节点的距离加上中间节点到该节点的距离。
4. 重复步骤2和步骤3,直到起点到终点的距离不再更新。
5. 最终得到起点到终点的最短路径。
Dijkstra算法的时间复杂度为O(N^2),其中N为节点的数目。
如果使用优先队列来维护距离起点最近的节点集合,则算法的时间复杂度可以降为O(NlogN),但是实际应用中优先队列的实现可能较为复杂。
Dijkstra算法可以用于有向图和无向图,但是不能处理带有负权边的图。
如果图中存在负权边,则可以使用Bellman-Ford算法来求解最短路径。
最短路径的实验报告最短路径的实验报告引言:最短路径问题是图论中一个经典的问题,涉及到在一个带有权重的图中找到两个顶点之间的最短路径。
本实验旨在通过实际操作和算法分析,深入探讨最短路径算法的性能和应用。
实验设计:本次实验使用了Dijkstra算法和Floyd-Warshall算法来解决最短路径问题。
首先,我们使用Python编程语言实现了这两个算法,并对它们进行了性能测试。
然后,我们选择了几个不同规模的图进行实验,以比较这两种算法的时间复杂度和空间复杂度。
最后,我们还在实际应用中使用了最短路径算法,以验证其实用性。
实验过程:1. 实现Dijkstra算法Dijkstra算法是一种贪心算法,用于求解单源最短路径问题。
我们首先实现了该算法,并对其进行了性能测试。
在测试中,我们使用了一个包含1000个顶点和5000条边的图,记录了算法的运行时间。
结果显示,Dijkstra算法的时间复杂度为O(V^2),其中V表示图中的顶点数。
2. 实现Floyd-Warshall算法Floyd-Warshall算法是一种动态规划算法,用于求解所有顶点对之间的最短路径。
我们在Python中实现了该算法,并对其进行了性能测试。
在测试中,我们使用了一个包含100个顶点和5000条边的图,记录了算法的运行时间。
结果显示,Floyd-Warshall算法的时间复杂度为O(V^3),其中V表示图中的顶点数。
3. 比较两种算法通过对Dijkstra算法和Floyd-Warshall算法的性能测试,我们可以看到,Dijkstra算法在处理较大规模的图时性能更好,而Floyd-Warshall算法在处理较小规模的图时性能更好。
因此,在实际应用中,我们可以根据图的规模选择合适的算法。
4. 应用实例为了验证最短路径算法的实际应用性,我们选择了一个城市交通网络图进行实验。
我们使用了Dijkstra算法来计算两个城市之间的最短路径,并将结果与实际的驾车时间进行比较。
在交通网络中,常常会提出许多这样的问题:两地之间是否有路相通?在有多条通路的情况下,哪一条最近?哪一条花费最少等。
交通网络可以用带权图表示,图中顶点表示域镇,边表示两城之间的道路,边上权值可表示两城镇间的距离,交通费用或途中所需的时间等。
以上提出的问题就是带权图中求最短路径的问题,即求两个顶点间长度最短的路径。
最短路径问题的提法很多。
在这里仅讨论单源最短路径问题:即已知有向图(带权),我们希望找出从某个源点S∈V到G中其余各顶点的最短路径。
例如:下图(有向图G14),假定以v1为源点,则其它各顶点的最短路径如下表所示:图G14从有向图可看出,顶点v1到v4的路径有3条:(v1,v2,v4),(v1,v4),(v1,v3,v2,v4),其路径长度分别为:15,20和10。
因此v1到v4的最短路径为(v1,v3,v2,v4 )。
为了叙述方便,我们把路径上的开始点称为源点,路径的最后一个顶点为终点。
那么,如何求得给定有向图的单源最短路径呢?迪杰斯特拉(Dijkstra)提出按路径长度递增产生诸顶点的最短路径算法,称之为迪杰斯特拉算法。
迪杰斯特拉算法求最短路径的实现思想是:设有向图G=(V,E),其中,V={0,2,…,n-1},cost是表示G的邻接矩阵,G.arcs [i][j] .adj 表示有向边<i,j>的权。
若不存在有向边<i,j>,则G.arcs [i][j] .adj 的权为无穷大(这里取值为32767)。
设S是一个集合,其中的每个元素表示一个顶点,从源点到这些顶点的最短距离已经求出。
设顶点v0为源点,集合S的初态只包含顶点v0。
数组D记录从源点到其他各顶点当前的最短距离,其初值为D[i]= G.arcs[v0][i].adj ,i=1,…,n-1。
从S之外的顶点集合V-S 中选出一个顶点w,使D[w]的值最小。
于是从源点到达w只通过S 中的顶点,把w加入集合S中调整D中记录的从源点到V-S中每个顶点v的距离:从原来的D[v] 和D[w]+ G.arcs [w][v] .adj中选择较小的值作为新的D[v]。
c语言最短路径的迪杰斯特拉算法Dijkstra的算法是一种用于查找图中两个节点之间最短路径的算法。
这个算法可以应用于有向图和无向图,但是它假设所有的边都有正权值,并且不包含负权值的边。
以下是一个简单的C语言实现:c复制代码#include<stdio.h>#define INF 99999#define V 5 // 顶点的数量void printSolution(int dist[]);void dijkstra(int graph[V][V], int src);int main() {int graph[V][V] = { { 0, 4, 0, 0, 0 }, { 4, 0, 8, 11, 7 },{ 0, 8, 0, 10, 4 },{ 0, 11, 10, 0, 2 },{ 0, 7, 4, 2, 0 } };dijkstra(graph, 0);return0;}void dijkstra(int graph[V][V], int src) { int dist[V];int i, j;for (i = 0; i < V; i++) {dist[i] = INF;}dist[src] = 0;for (i = 0; i < V - 1; i++) {int u = -1;for (j = 0; j < V; j++) {if (dist[j] > INF) continue;if (u == -1 || dist[j] < dist[u]) u = j;}if (u == -1) return;for (j = 0; j < V; j++) {if (graph[u][j] && dist[u] != INF && dist[u] + graph[u][j] < dist[j]) {dist[j] = dist[u] + graph[u][j];}}}printSolution(dist);}void printSolution(int dist[]) {printf("Vertex Distance from Source\n"); for (int i = 0; i < V; i++) {printf("%d \t\t %d\n", i, dist[i]);}}这个代码实现了一个基本的Dijkstra算法。
c语言实现迪杰斯特拉算法实例========迪杰斯特拉算法是一种用于求解单源最短路径问题的算法,它使用Dijkstra 算法的思想,通过不断更新最短路径值,最终找到源节点到所有其他节点的最短路径。
下面是一个使用C语言实现迪杰斯特拉算法的实例。
一、算法概述------迪杰斯特拉算法的基本思想是:从源节点开始,不断更新与源节点相邻的节点之间的最短路径值,直到所有节点都被处理完毕。
算法的核心是使用一个最小堆来存储待处理的节点及其对应的距离值,每次从最小堆中取出距离值最小的节点,并更新与其相邻节点的距离值。
二、代码实现------以下是一个使用C语言实现迪杰斯特拉算法的示例代码:```c#include <stdio.h>#include <stdlib.h>#include <limits.h>#define MAX_NODES 100 // 最大节点数#define INF 0x3f3f3f3f // 无穷大值typedef struct Node {int id; // 节点编号int distance; // 到源节点的距离struct Node* nxt; // 指向下一个节点的指针(用于广度优先搜索)} Node;// 创建新节点Node* create_node(int id) {Node* node = (Node*)malloc(sizeof(Node));node->id = id;node->distance = INF;node->nxt = NULL;return node;}// 将节点添加到最小堆中(假设堆为head)void add_node_to_heap(Node** head, int* size, int distance) {Node* node = create_node(distance); // 创建新节点(*size)++; // 节点数加一(*head)->distance = distance; // 将新节点距离设置为最小值(*head)->nxt = node; // 将新节点添加到堆中while (*head->nxt != NULL && (*head->nxt)->distance < (*head)->distance) { // 调整堆中距离值最小节点的位置Node* temp = *head->nxt; // 保存当前距离最小的节点(*head)->nxt = (*head->nxt)->nxt; // 将当前节点的下一个节点向前移动一位(退出循环)free(temp); // 释放当前节点的内存空间(释放内存)}}// 从最小堆中取出距离值最小的节点(返回值为距离值)int extract_min(Node** head, int* size) {Node* temp = *head; // 保存当前距离最小的节点(用于后续更新)int min_distance = temp->distance; // 当前最小距离值(用于后续更新)Node** p = *head; // 指向当前距离最小的节点的指针(用于后续更新)while (p->nxt != NULL && p->distance > min_distance) { // 从堆中取出距离值最小的节点,并更新指针和距离值Node* next_node = p->nxt; // 保存下一个节点指针(用于广度优先搜索)*p = p->nxt->nxt; // 将当前节点的下一个节点向前移动一位(退出循环)p->distance = min_distance; // 将当前节点的距离值更新为当前最小值free(next_node); // 释放下一个节点的内存空间(释放内存)}*head = p->nxt; // 将当前节点的下一个节点设置为堆头指针(进入下一轮循环)*size--; // 删除已处理节点数减一(返回最小距离值)return min_distance; // 返回最小距离值(作为结果返回)}// 迪杰斯特拉算法主函数(源代码)void dijkstra(int nodes, int start_node, Node** nodes_list) {int size = nodes; // 初始化节点数和距离数组大小为0(初始化)Node* heap = (Node*)malloc(sizeof(Node) * size); // 创建最小堆(初始化)for (int i = 0; i < size; i++) { // 将所有节点添加到堆中,并设置其距离值为无穷大(进入主循环)add_。
最短路径实验报告最短路径实验报告引言:最短路径算法是计算机科学中的一个经典问题,它在许多领域中都有广泛的应用,如交通规划、电路设计、网络通信等。
本实验旨在通过实践探索最短路径算法的实际应用,并对其性能进行评估。
一、问题描述:我们将研究一个城市的交通网络,其中包含多个节点和连接这些节点的道路。
每条道路都有一个权重,表示通过该道路所需的时间或距离。
我们的目标是找到两个节点之间的最短路径,即使得路径上各个道路权重之和最小的路径。
二、算法选择:为了解决这个问题,我们选择了Dijkstra算法和Floyd-Warshall算法作为比较对象。
Dijkstra算法是一种单源最短路径算法,它通过不断选择当前最短路径的节点来逐步扩展最短路径树。
Floyd-Warshall算法则是一种多源最短路径算法,它通过动态规划的方式计算任意两个节点之间的最短路径。
三、实验设计:我们首先构建了一个包含10个节点和15条道路的交通网络,每条道路的权重随机生成。
然后,我们分别使用Dijkstra算法和Floyd-Warshall算法计算两个节点之间的最短路径,并记录计算时间。
四、实验结果:经过实验,我们发现Dijkstra算法在计算单源最短路径时表现出色,但是在计算多源最短路径时效率较低。
而Floyd-Warshall算法在计算多源最短路径时表现出色,但是对于大型网络的单源最短路径计算则需要较长的时间。
五、性能评估:为了评估算法的性能,我们对不同规模的交通网络进行了测试,并记录了算法的计算时间。
实验结果显示,随着交通网络规模的增大,Dijkstra算法的计算时间呈指数级增长,而Floyd-Warshall算法的计算时间则呈多项式级增长。
因此,在处理大型网络时,Floyd-Warshall算法具有一定的优势。
六、实际应用:最短路径算法在实际应用中有着广泛的用途。
例如,在交通规划中,最短路径算法可以帮助我们找到最优的行车路线,减少交通拥堵。
dijkstra算法城市最短路径问题Dijkstra算法是一种经典的图算法,用于求解带有非负权重的图的单源最短路径问题。
在城市的交通规划中,Dijkstra算法也被广泛应用,可以帮助我们找到最短的路线来节省时间和成本。
一、最短路径问题的定义最短路径问题,指的是在一个带权重的有向图中,找到从起点到终点的一条路径,它的权重之和最小。
在城市的交通规划中,起点和终点可以分别是两个街区或者两个交通枢纽。
二、Dijkstra算法Dijkstra算法是基于贪心策略的一种算法,用于解决带非负权重的最短路径问题。
它采用了一种贪心的思想:每次从起点集合中选出当前距离起点最近的一个点,把其移到已知的最短路径集合中。
并以该点为中心,更新它的相邻节点的到起点的距离。
每次更新距离时,选择距离起点最近的距离。
三、Dijkstra算法实现1. 创建一个到起点的距离数组和一个布尔类型的访问数组。
2. 将起点的到起点的距离设置为0,其他的节点设置为无穷大。
3. 从距离数组中选择没有访问过且到起点距离最近的点,将它标记为“已访问”。
4. 对于它的所有邻居,如果出现路径缩短的情况,就更新它们的距离。
5. 重复步骤3和4,直到所有节点都被标记为“已访问”。
6. 最后,根据到起点的距离数组,以及每个节点的前驱节点数组,可以得到从起点到终点的最短路径。
四、Dijkstra算法的时间复杂度Dijkstra算法的时间复杂度可以通过堆优化提高,但最坏情况下时间复杂度仍达到O(ElogV)。
其中,E是边的数量,V是顶点的数量。
因此,Dijkstra算法在不考虑空间复杂度的情况下,是一种高效且实用的解决城市最短路径问题的算法。
五、结论Dijkstra算法是一个广泛应用于城市交通规划领域的算法,可以帮助我们找到最优的路线来节省时间和成本。
它基于贪心策略,每次从起点集合中选择距离起点最近的点,并对其邻居节点进行松弛操作。
Dijkstra算法的时间复杂度虽然较高,但堆优化可以提高算法性能。
最短路径——dijkstra算法代码(c语⾔)最短路径问题看了王道的视频,感觉云⾥雾⾥的,所以写这个博客来加深理解。
(希望能在12点以前写完)()⼀、总体思想1.初始化三个辅助数组s[],dist[],path[]s[]:这个数组⽤来标记结点的访问与否,如果该结点被访问,则为1,如果该结点还没有访问,则为0;dist[]:这个数组⽤来记录当前从v到各个顶点的最短路径长度,算法的核⼼思想就是通过不断修改这个表实现; path[]:这个数组⽤来存放最短路径;2.遍历图,修改上⾯的各项数组,每次只找最短路径,直到遍历结束⼆、代码实现1void dijkstra(Graph G, int v)2 {3int s[G.vexnum];4int dist[G.vexnum];5int path[G.vexnum];6for(int i = 0; i < G.vexnum; i++)7 {8 s[i] = 0;9 dist[i] = G.edge[v][i];10if(G.edge[v][i] == max || G.edge[v][i] == 0)11 {12 path[i] = -1;13 }14else15 {16 path[i] = v;17 }18 s[v] = 1;19 }2021for(int i = 0; i < G.vexnum; i++)22 {23int min = max;24int u;25for(int j = 0; j < G.vexnum; j++)26 {27if(s[j] != 1 && dist[j] < min)28 {29 min = dist[j];30 u = j;31 }32 }33 s[u] = 1;34for(int j = 0; j < G.vexnum; j++)35 {36if(s[j] != 1 && dist[j] > dist[u] + G.edge[u][j])37 {38 dist[j] = dist[u] + G.edge[u][j];39 path[j] = u;40 }41 }42 }43 }三、代码解释先⾃⼰定义⼀个⽆穷⼤的值max#define max infdijkstra算法传⼊的两个参为图Graph G;起点结点 int v;⾸先我们需要三个辅助数组1int s[G.vexnum];//记录结点时是否被访问过,访问过为1,没有访问过为02int dist[G.vexnum];//记录当前的从v结点开始到各个结点的最短路径长度3int path[G.vexnum];//记录最短路径,存放的是该结点的上⼀个为最短路径的前驱结点初始化三个数组1for(int i = 0; i < G.vexnum; i++)2 {3 s[i] = 0;//⽬前每个结点均未被访问过,设为04 dist[i] = G.edge[v][i];//dist[]数组记录每个从v结点开到其他i结点边的长度(权值)5if(G.edge[v][i] == max || G.edge[v][i] == 0)6 {7 path[i] = -1;8 }//如果v到i不存在路径或者i就是v结点时,将path[i]设为-1,意为⽬前v结点不存在路径到i9else10 {11 path[i] = v;12 }//反之,若v到i存在路径,则v就是i的前驱结点,将path[i] = v13 s[v] = 1;//从遍历起点v开始,即已经访问过顶点s[v]=114 }开始遍历数组并且每次修改辅助数组以记录⽬前的情况,直⾄遍历结束1for(int i = 0; i < G.vexnum; i++)2 {3int min = max;//声明⼀个min = max⽤来每次记录这次遍历找到的最短路径的长度(权值)4int u;//声明u来记录这次历找到的最短路径的结点5for(int j = 0; j < G.vexnum; j++)//开始遍历找⽬前的最短路径6 {7if(s[j] != 1 && dist[j] < min)8 {9 min = dist[j];10 u = j;11 }//找出v到结点j的最短路径,并且记录下最短路径的结点u = j12 }13 s[u] = 1;//找到结点u,即已访问过u,s[u] = 114for(int j = 0; j < G.vexnum; j++)//开始遍历修改辅助数组的值15 {16if(s[j] != 1 && dist[j] > dist[u] + G.edge[u][j])17 {18 dist[j] = dist[u] + G.edge[u][j];19 path[j] = u;20 }//如果v→j的路径⽐v →u→j长,那么修改dist[j]的值为 dist[u] + G.edge[u][j],并且修改j的前驱结点为path[j] = u21 }22 }遍历结束后,数组dist[]就是存放了起点v开始到各个顶点的最短路径长度最短路径包含的结点就在path数组中例如我们得到如下的path[]数组1 path[0] = -1;//0到⾃⼰⽆前驱结点2 path[1] = 0;//1的前驱为结点0,0⽆前驱结点,即最短路径为0 →13 path[2] = 1;//2的前驱结为点1,1的前驱结点0,0⽆前驱结点,即最短路径为0 →1 →24 path[3] = 0;//3的前驱为结点0,0⽆前驱结点,即最短路径为0 →35 path[4] = 2;//4的前驱结为点2,2的前驱结为点1,1的前驱结点0,0⽆前驱结点,即最短路径为0 →1 →2 →4 dijkstra对于存在负权值的图不适⽤,明天再更新Floyd算法叭。
matlab dijkstra算法求解最短路径例题摘要:一、Dijkstra 算法简介1.Dijkstra 算法背景2.Dijkstra 算法原理二、MATLAB 实现Dijkstra 算法求解最短路径1.创建图对象2.计算最短路径3.可视化结果三、Dijkstra 算法应用示例1.例题描述2.解题步骤3.结果分析正文:一、Dijkstra 算法简介Dijkstra 算法是一种经典的图论算法,用于计算图中两个节点之间的最短路径。
它是由荷兰计算机科学家Edsger W.Dijkstra 于1956 年提出的,其基本思想是以起始点为中心向外层层扩展,直到扩展到终点为止。
Dijkstra 算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。
可以用堆优化来提高效率。
二、MATLAB 实现Dijkstra 算法求解最短路径1.创建图对象首先,我们需要使用MATLAB 的graph 函数创建一个图对象,指定节点和边的信息。
例如,我们创建一个简单的图,包含4 个节点和3 条边:```matlabG = graph(4, 3);```其中,4 表示图中有4 个节点,3 表示图中有3 条边。
2.计算最短路径接下来,我们可以使用MATLAB 的shortestpath 函数计算两个节点之间的最短路径。
例如,我们计算节点1 到节点3 的最短路径:```matlabSP = shortestpath(G, 1, 3);```3.可视化结果最后,我们可以使用MATLAB 的plot 函数将最短路径可视化。
例如,我们绘制节点和边以及最短路径:```matlabplot(G, SP);```三、Dijkstra 算法应用示例以下是一个使用Dijkstra 算法求解最短路径的例题:在一个图中,有4 个节点和3 条边,如下所示:```1 --2 -- 3| /| /| /| /|/4```请问,节点1 到节点4 的最短路径是多少?。
课程设计任务书目录1 需求分析............................................................................................ - 1 -2 算法基本原理 ................................................................................... - 2 -3 类设计................................................................................................ - 3 -4 详细设计............................................................................................ - 5 -4.1类的接口设计 . (5)4.2类的实现 (5)4.3主函数设计 (7)5 DOS界面程序运行结果及分析 ....................................................... - 8 -5.1程序运行结果 . (8)5.2运行结果分析 (9)6 基于MFC的图形界面程序开发..................................................... - 9 -6.1基于MFC的图形界面程序设计.. (10)6.2程序测试 (13)6.3MFC程序编写总结 (14)7 参考文献.......................................................................................... - 15 -1 需求分析Dijkstra 算法是由荷兰计算机科学家艾兹格·迪科斯彻发现的。
算法解决的是有向图中最短路径问题。
举例来说,如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离。
Dijkstra 算法可以用来找到两个城市之间的最短路径。
Dijkstra 算法的输入包含了一个有权重的有向图G ,以及G 中的一个来源顶点S 。
我们以V 表示G 中所有顶点的集合。
图中的每一个边,都是两个顶点所形成的有序元素对。
(u ,v )表示从顶点u 到v 有路径相连。
假设E 为所有边的集合,而边的权重则由权重函数w : E → [0, ∞]定义。
因此,w (u ,v )就是从顶点u 到顶点v 的非负花费值(cost)。
边的花费可以想像成两个顶点之间的距离。
任两点间路径的花费值,就是该路径上所有边的花费值总和。
已知有V 中有顶点s 及t ,Dijkstra 算法可以找到s 到t 的最低花费路径(i.e. 最短路径)。
这个算法也可以在一个图中,找到从一个顶点s 到任何其他顶点的最短路径。
1.如果将交通网络化成带权图,假如用顶点表示城市,边表示公路段,则由这些顶点和边组成的图可表示沟通个城市的公路图,边的权用以表示两个城市之间的距离或者表示走过这段公路所需要的时间或通过这段路的难易程度等。
作为司机和乘汽车的人,自然会关心如下两个问题:(1)从甲地到乙地是否有公路?(2)从甲地到乙地有几条公路,哪条公路最短或花费的代价最小? 这就是我们要讨论的最短路径问题。
2.迪杰斯特拉提出的一个求最短路径的算法。
其基本思想是:按路径长度递增的顺序,逐个产生各最短路径。
3.首先引进辅助向量dist[],它的每一个分量dist[i]表示已经找到的且从源点0v 到每一个终点i v 的当前最短路径长度。
它的初态为:如果从0v 到i v 有弧,则dist[i]为弧的权值;否则dist[i]为∞。
其中,长度为dist[j]=min{dist[i]|i v ∈V}的路径是从0v 出发的长度最短的一条最短路径,此路径为(0v ,i v )。
2 算法基本原理根据以上分析,可以得到如下描述的算法:①假设用带权的邻接矩阵arce[i][j]来表示带权有向图,arce[i][j]表示弧<i v ,j v >上的权值。
若<i v ,j v >不存在,则置arce[i][j]为∞(在计算机上可用允许的最大值代替)。
S 为已找到的从0v 出发的最短路径的终点的集合,它的初始状态为空集。
那么,从0v 出发到图上其余个顶点(终点)i v 可能达到的最短路径长度的初值为:dist[i]=arce[Locate Vex(G,0v )][i]i v ∈S ②选择j v 得dist[j]=min{dist[i]|i v ∈V-S}j v 就是当前求得的一条从0v 出发的最短路径的终点。
令S=S ∪{j}。
③修改从0v 出发到集合V-S 上任一顶点k v 可达的最短顶点长度。
如果 dist[j]+arce[j][k]<dist[k]则修改dist[k]为dist[k]=dist[j]+arce[j][k]④重复操作②、③共n-1次。
由此求得从0v 到图上其余各顶点的最短路径是依路径长度递增的序列。
用Dijkstra 算法求有向图G 的0v 顶点到其余顶点v 的最短路径P[v]及其带权长度D[v]。
这个算法是通过为每个顶点v 保留目前为止所找到的从s 到v 的最短路径来工作的。
初始时,源点s 的路径长度值被赋为0(d[s]=0), 同时把所有其他顶点的路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径(对于V 中所有顶点v 除s 外d[v]= ∞)。
当算法结束时,d[v]中储存的便是从s 到v 的最短路径,或者是无穷大(如果路径不存在的话)。
Dijstra算法的基础操作是边的拓展:如果存在一条从u到v的边,那么从s 到v的最短路径可以通过将边(u,v)添加到s到u的尾部来拓展。
这条路径的长度是d[u]+w(u,v)。
如果这个值比目前已知的d[v]的值要小,我们可以用新值来替代当前d[v]中的值。
拓展边的操作一直执行到所有的d[v]都代表从s到v最短路径的花费。
这个算法经过适当的组织因而当d[u]达到它最终的值的时候,每条边(u,v)都只被拓展一次。
算法维护两个顶点集S和Q。
集合S保留了我们已知的所有d[v]的值已经是最短路径的值顶点,而集合Q则保留其他所有顶点。
集合S初始状态为空,而后每一步都有一个顶点从Q移动到S。
这个被选择的顶点是Q中拥有最小的d[u]值的顶点。
当一个顶点u从Q中转移到了S中,算法对每条外接边(u,v)进行拓展。
Dijkstra(G,D,s){//用Dijkstra算法求有向网G的源点s到各顶点的最短路径长度//以下是初始化操作S={s};D[s]=0;//设置初始的红点集及最短距离for( all i∈V-S )do //对蓝点集中每个顶点iD[i]=G[s][i];//设置i初始的估计距离为w<s,i>//以下是扩充红点集for(i=0;i<n-1;i++)do{//最多扩充n-1个蓝点到红点集D[k]=min{D[i]:all i V-S};//在当前蓝点集中选估计距离最小的顶点kif(D[k]等于∞)return;//蓝点集中所有蓝点的估计距离均为∞时,//表示这些顶点的最短路径不存在。
S=S∪{k};//将蓝点k涂红后扩充到红点集for( all j∈V-S )do //调整剩余蓝点的估计距离if(D[j]>D[k]+G[k][j])//新红点k使原D[j]值变小时,用新路径的长度修改D[j],//使j离s更近。
D[j]=D[k]+G[k][j];}}3 类设计从上面的算法分析可以看到,根据算法设计了类class SPFA,public: intn;表示图里面的点数,public: int path[MAX][MAX];定义链接矩阵最多是1000个点,public: int dis[MAX];定义源点到其他点的距离,public: int src;定义源点,bool used[MAX]={false};定义点是否访问过了,初始化为未访问,初始化一下到各个点的距离,如果从k 点走到j 点的路很比原来的要短,那么更新,采用图的邻接矩阵或邻接表实现最短路径问题中图的存储,采用Dijkstra 算法求从某个源点到其余各顶点的最短路径。
第一步 先取()10W v =意即1v 到1v 的距离为0,而()j T v 是对()j T v 所赋的初值。
第二步 利用()1W v 已知,根据()(){}min ,j i ij T v W v w +对()j T v 进行修正。
第三步 对所有修正后的()j T v 求出其最小者()k T v 。
其对应的点k v 是1v 所能一步到达的点j v 中最近的一个,由于所有()0W u ≥。
因此任何从其它点j v 中转而到达k v 的通路上的距离都大于1v 直接到k v 的距离()k T v ,因此()k T v 就是1v 到k v 的最短距离,所以在算法中令()()k k W v T v =并从s 中删去k v ,若k=n 则()()k n W v W v =就是1v 到n v 的最短路线,计算结束。
否则令i k v v =回到第二步,继续运算,直到k=n 为止。
这样每一次迭代,得到1v 到一点k v 的最短距离,重复上述过程直到k n v v =。
Floyd 算法的基本原理和实现方法为:如果一个矩阵ij D d ⎡⎤=⎣⎦其中0ij d >表示i 与j 间的距离,若i 与j 间无路可通,则ij d 为无穷大。
i 与j 间的最短距离存在经过i 与j 间的k 和不经过k 两种情况,所以可以令1,2,3,,k n =L ,n(n 为节点数)。
检查ij d 与ik kj d d +的值,在此,ik d 与kj d 分别为目前所知的i 到k 与k 到j 的最短距离,因此,ik kj d d +就是i 到j 经过k 的最短距离。
所以,若有ij ik kj d d d >+,就表示从i 出发经k 再到j 的距离要比原来的i 到j 距离短,自然把i 到j 的ij d 重写成ik kj d d +。
每当一个k 搜索完,ij d 就是目前i 到j 的最短距离。
重复这一过程,最后当查完所有k 时,ij d 就为i 到j 的最短距离。
4 详细设计首先,这个程序定义了一个类class SPFA,通过此类定义链接矩阵,采用图的邻接矩阵或邻接表实现最短路径问题中图的存储,然后通过主函数main调用class来实现,采用Dijkstra算法求从某个源点到其余各顶点的最短路径。