数据结构——图——最短路径D&F算法
一、Dijkstra算法(贪心地求最短距离的算法)
在此算法中,我按照自己的理解去命名,理解起来会轻松一些。
#define MAXSIZE 100 #define UNVISITED 0 #define VISITED 1 #define INFINITY 66666 typedef struct tool { int visited[MAXSIZE]; /*是否已访问的数组,visited[i]表示顶点i已经访问,也就是到顶点i的最短距离已求出*/ int known_shortest_distance[MAXSIZE]; /*已知的最短距离数组。known_shortest_distance[i]代表从V0到Vi的最短距离*/ int previous_vertex[MAXSIZE]; /*previous_vertex[i]=j,代表:在从V0到Vi的最短路径上,顶点i的前一个顶点是顶点j*/ } Tool; typedef struct gragh { int num_of_vertexes; int adjacent_matrix[MAXSIZE][MAXSIZE]; } Gragh; void init_tool(Gragh g, Tool &t) { ; ; i < g.num_of_vertexes; i++) { t.visited[i] = UNVISITED; t.known_shortest_distance[i] = g.adjacent_matrix[][i]; t.previous_vertex[i] = ; } } void dijstra_shortest_distance(Gragh g, Tool &t) { int i, j, x; //循环变量 int min_distance, x_index; /*min_distance存储的是当前已知的最短距离数组中从V0到Vx最小的距离; x_index存储的Vx的下标*/ init_tool(g, t); ; i < g.num_of_vertexes; i++) { min_distance = INFINITY; ; x < g.num_of_vertexes; x++) { if(!t.visited[x] && t.known_shortest_distance[x] < min_distance) { min_distance = t.known_shortest_distance[x]; x_index = x; } } /*通过上面一个循环,最短距离数组中的最小值就是min_distance; 该顶点的下标就是x_index; 在当前没有访问且以V0为起点距离最短的顶点中, 这个点的下标就是x_index.*/ t.visited[x_index] = VISITED; ; j < g.num_of_vertexes; j++) { if(!t.visited[j] && (min_distance + g.adjacent_matrix[x_index][j] < t.known_shortest_distance[j])) { t.known_shortest_distance[j] = min_distance + g.adjacent_matrix[x_index][j]; t.previous_vertex[j] = x_index; } } } }
如果要求任意两点之间的最短距离:只需在外层加一层循环,把最短距离数组和previous_vertex数组变成二维数组即可。
输出从V0到Vi的最短距离和完整路径:
#include<stack> void print_path(Tool &t, int dest) { int i = dest; stack<int> s; cout << "从V0到V" << i << "的最短距离:" << t.known_shortest_distance[i] << endl; ) { s.push(t.previous_vertex[i]); i = t.previous_vertex[i]; } cout << "从V0到V" << i << "的路径:"; cout<<"V0"; while(!s.empty()) { cout << "->V" << s.top(); s.pop(); } cout << "->V" << dest; }
一、Floyd算法(不管三七二十一,先把整个图中任意两点的最短距离求出再说)
核心思想:对图中任意两个顶点(即下面代码中的j和k),如果能在其他顶点中(也就是下面代码中的i,在原始版本中,i和j,k可以相同)找到一个顶点i,使得顶点j到顶点i的距离加上顶点i的距离到顶点k的距离比直接从顶点j到顶点k的距离短,那么,就修改顶点j到顶点k的距离。
typedef struct floyd_tool { int known_shortest_distance[MAXSIZE][MAXSIZE]; /*已知的最短距离数组。known_shortest_distance[i][j]代表从Vi到Vj的最短距离*/ int path_matrix[MAXSIZE][MAXSIZE]; /*path_matrix[i][j]=k,代表:在从Vi到Vj的最短路径上,要经过顶点k; 用k代替i,直到path_matrix[k][j]=j*/ } FloydTool; void init_floyd_tool(FloydTool &ft, Gragh g) { ; i < g.num_of_vertexes; i++) { ; j < g.num_of_vertexes; j++) { ft.known_shortest_distance[i][j] = g.adjacent_matrix[i][j]; ft.path_matrix[i][j] = j; } } } void floyd_shortest_distance(Gragh g,FloydTool &ft) { init_floyd_tool(ft,g); ;i < g.num_of_vertexes; i++){ ;j < g.num_of_vertexes;j++){ ;k < g.num_of_vertexes;k++){ if(ft.known_shortest_distance[j][k] > ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k]){ ft.known_shortest_distance[j][k] = ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k]; ft.path_matrix[j][k] = ft.path_matrix[j][i]; } } } } }
改进版:
改进依据:由上面初始版本的思想可知,对于任意两个顶点j和顶点k,如果顶点j和顶点i是同一个,那么,最里面一层的比较相当于是D和0+D在比,显然,这是没必要的。或者,如果j和i不相等,但是i不是j的邻接点,那么j到i的距离就是“无穷大”,很显然,通过这个桥梁i是不可能缩短j到k的距离的。所以,有了第一个if;同理,第二个if也是这么来的。然后,初始版本中,最里面两层循环的循环变量都是从0开始的,但是因为我们考虑的是无向图,j到k的距离和k到j的距离是一样的,所以,我在改进版本中减去了重复求k到j的距离。
void floyd_shortest_distance(Gragh g,FloydTool &ft) { init_floyd_tool(ft,g); ;i < g.num_of_vertexes; i++){ ;j < g.num_of_vertexes;j++){ if(j == i || ft.known_shortest_distance[j][i] == INFINITY)continue; for(int k = j + 1;k < g.num_of_vertexes;k++){ if(k == i || ft.known_shortest_distance[k][i] == INFINITY)continue; if(ft.known_shortest_distance[j][k] > ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k]){ ft.known_shortest_distance[j][k] = ft.known_shortest_distance[j][i] + ft.known_shortest_distance[i][k]; ft.path_matrix[j][k] = ft.path_matrix[j][i]; } } } } }
输出最短距离和完整路径:
void print_path(FloydTool &ft,int orig,int dest) { cout << "从V"<<orig<<"到V"<<dest<< "的最短距离:" << ft.known_shortest_distance[orig][dest] << endl; cout << "从V"<<orig<<"到V"<<dest<<"的路径:"; cout<<"V"<<orig; while(ft.path_matrix[orig][dest] != dest){ cout<<"->V"<<ft.path_matrix[orig][dest]; orig = ft.path_matrix[orig][dest]; } cout << "->V" << dest; }
数据结构——图——最短路径D&F算法的更多相关文章
- 算法学习记录-图——最短路径之Dijkstra算法
在网图中,最短路径的概论: 两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点. 维基百科上面的解释: 这个算法是通过为每个顶点 v 保留目前为止所找到的从 ...
- 算法与数据结构(六) 迪杰斯特拉算法的最短路径(Swift版)
上篇博客我们详细的介绍了两种经典的最小生成树的算法,本篇博客我们就来详细的讲一下最短路径的经典算法----迪杰斯特拉算法.首先我们先聊一下什么是最短路径,这个还是比较好理解的.比如我要从北京到济南,而 ...
- 数据结构与算法--最短路径之Bellman算法、SPFA算法
数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...
- 数据结构与算法--最短路径之Floyd算法
数据结构与算法--最短路径之Floyd算法 我们知道Dijkstra算法只能解决单源最短路径问题,且要求边上的权重都是非负的.有没有办法解决任意起点到任意顶点的最短路径问题呢?如果用Dijkstra算 ...
- 数据结构与算法--最短路径之Dijkstra算法
数据结构与算法--最短路径之Dijkstra算法 加权图中,我们很可能关心这样一个问题:从一个顶点到另一个顶点成本最小的路径.比如从成都到北京,途中还有好多城市,如何规划路线,能使总路程最小:或者我们 ...
- <数据结构>图的最短路径问题
目录 最短路径问题 Dijstra算法:中介点优化 基本步骤 伪代码 在实现过程中的关键问题 代码实现 邻接矩阵版 邻接表版 时间复杂度:O(VlogV+E) 算法存在的问题:存在负权边时会失效 Be ...
- 【算法设计与分析基础】25、单起点最短路径的dijkstra算法
首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...
- JavaScript数据结构——图的实现
在计算机科学中,图是一种网络结构的抽象模型,它是一组由边连接的顶点组成.一个图G = (V, E)由以下元素组成: V:一组顶点 E:一组边,连接V中的顶点 下图表示了一个图的结构: 在介绍如何用Ja ...
- 数据结构C语言版 弗洛伊德算法实现
/* 数据结构C语言版 弗洛伊德算法 P191 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h>#include <limits.h> # ...
随机推荐
- HDU 2577 How to Type (DP,经典)
题意: 打字游戏,求所按的最少次数.给出一个串,其中有大小写,大写需要按下cap键切换到大写,或者在小写状态下按shift+键,这样算两次,打小写时则相反.注意:在打完所有字后,如果cap键是开着的, ...
- acdream 1412 2-3Trees (组合+DP)
题意:2-3树的每个结点(除了叶子外)有2或3个孩子(分支),假设是一个满2-3树,那么给出叶子的数量,求这样的树有多少棵.(注:有2个孩子的结点视为相同,有3个孩子的结点视为相同,比如倒数第2层有4 ...
- 《摇滚南京》——"人生下来就是孤独"
昨天是纪录片<摇滚南京>东南大学站的展映分享会 我不是一个摇滚迷,作为学渣狗看论文.码代码的时候会塞个耳机,平时其实民谣听得更多一点,摇滚觉得有点高大上.所以整好趁着学校有活动,也跟着高大 ...
- 嵌入式 hi3518平台指定网卡测试是否通外网
版权声明:本文为博主原创文章,未经博主允许不得转载. /********************************** (C) COPYRIGHT *********************** ...
- Oracle自定义数据类型 1
原文 oracle 自定义类型 type / create type 一 Oracle中的类型 类型有很多种,主要可以分为以下几类: 1.字符串类型.如:char.nchar.varchar2.nva ...
- C++ STL算法系列5---equal() , mismatch()
equal和mismatch算法的功能是比较容器中的两个区间内的元素.这两个算法各有3个参数first1,last1和first2.如果对 于区间[first1,last1)内所有的first1+i, ...
- Android实现button一边圆角一边直角
http://www.it165.net/pro/html/201503/36211.html
- 把raw目录下的几张照片存放到SD卡里面去
try { //SD卡路径 String filename =android.os.Environment .getExternalStorageDirectory().getAbsolutePath ...
- [转]Linux的tail 与head 命令
转自:http://blog.csdn.net/carolzhang8406/article/details/6112707 head命令是用来查看具体文件的前面几行的内容,具体格式如下: head ...
- linux库文件编写入门(笔记)
linux库文件的编写 作者: laomai地址: http://blog.csdn.net/laomai 本文主要参考了如下资料⑴hcj写的"Linux静态/动态链接库的创建和使用&quo ...