Dijkstra——单源最短路径
算法思想
①从一个源点开始,找距离它最近的点顶点v
②然后以顶点v为起点,去找v能到达的顶点w,即v的邻居
比较源点直接到 v的距离和(源点到v的距离+v到w的距离)
若大于后者则更新源点的到w的开销
③然后去掉这个顶点v,去寻找下一个到距离源点最近的顶点重复②
最后更新完所有顶点
算法思路
1.用邻接表或者一个二维数组(邻接矩阵)来存储图
2.设置dist存储到源点的最短距离
known标记顶点是被处理
path记录路径(到达该顶点的上一个顶点)
3.这步的实现和算法思想中描述的一样
4.递归显示出源点到各个顶点的路径
代码实现
下面是完整的代码实现,分别用了邻接表和邻接矩阵来存图
样图如下
邻接矩阵存图
#include <iostream> #include <cstdlib> #define Infinity 10000 #define VERSIZE 8 #define notvertex -1 using namespace std; typedef int Vertex; int dist[VERSIZE];//存储各顶点到源点的最短距离 bool S[VERSIZE];//将处理过的顶点设置为true Vertex path[VERSIZE];//存储到该顶点的上一个顶点 void ReadGraph(int Graph[VERSIZE][VERSIZE], int m)// 边m { ; Vertex u, v; int weight; ; i <= m; i++) { cout << "请输入第" << i << "条边:"; cin >> u >> v; cout << "请输入边(" << u << "," << v << ")的权重:"; cin >> weight; Graph[u][v] = weight; } } //在没处理过的顶点里 找出距离源点最近的顶点 Vertex FindMinIndex() { int min = Infinity; Vertex min_index = ; ; i< VERSIZE; i++) { if (!S[i] && dist[i]<min) { min = dist[i]; min_index = i; } } return min_index; } //算法关键 void Dijkstra(int Graph[VERSIZE][VERSIZE], Vertex source) { ; // 初始化数组 从顶点为1开始能直接到达source的 初始化dis数组 0代表不可达 ; i < VERSIZE; i++) { dist[i] = (Graph[source][i] == ? Infinity : Graph[source][i]); S[i] = false; if (dist[i] != Infinity) path[i] = source; else path[i] = notvertex; } //源点到自身 dist[source] = ; S[source] = true; //循环VERSIZE-1次 ; count < VERSIZE; count++) { Vertex u = FindMinIndex();//找出距离源点最近的顶点 S[u] = true;//标记为已知 ; v < VERSIZE; v++) { && !S[i])//u可达v 且 v未知 { if (dist[v] >(Graph[u][v] + dist[u])) { dist[v] = Graph[u][v] + dist[u]; path[v] = u; } } } } } void PrintDist(Vertex source) { ; printf("Source vertex Dist\n"); ; i< VERSIZE; i++) { if (dist[i] != Infinity) printf("%d -> %d\t%d\n", source, i, dist[i]); else printf("%d -> %d\tInfinity\n", source, i); } } //输出路径 void PrintPath(int v) { if (path[v] != notvertex) { PrintPath(path[v]); printf("--->"); } printf("%d", v); } int main() { ,j=; }; ; i < VERSIZE; i++)//初始化二维数组 { ; j < VERSIZE; j++) Graph[i][j] = ; } ReadGraph(Graph, ); Dijkstra(Graph, );//源点是1 PrintDist(); printf("源点1顶点7的路径:\n"); PrintPath();//打印从源点到顶点7的路径 system("pause"); ; }
运行结果
邻接表存图
#include <iostream> #include <cstdlib> #define VERSIZE 8 #define NotVertex -1 #define Infinity 100000 using namespace std; typedef int Vertex; typedef struct vernode VerNode;//定义顶点结构 typedef struct tablelist Table;//定义邻接表 struct vernode { Vertex ver; int weight;//权重 VerNode * pNext; }; struct tablelist { VerNode header; bool known; int dist; Vertex path; }T[VERSIZE]; //初始化标表+读图 void InitTable(Table T[], int n, int m)//顶点数n 边数m { ; ; i <= n; i++)//初始化表头 { T[i].header.ver = i; T[i].header.weight = ;//到自身的权重为0 T[i].header.pNext = NULL; T[i].dist = Infinity; T[i].known = false; T[i].path = NotVertex; } Vertex u, v;//边(u,v) ; VerNode * ptemp; ; i <= m; i++) { cout << "请输入第" << i << "条边:"; cin >> u >> v; cout << "请输入边(" << u <<","<< v << ")的权重:"; cin >> wei; ptemp = (VerNode*)malloc(sizeof(VerNode)); ptemp->ver = v; ptemp->weight = wei; ptemp->pNext = T[u].header.pNext; T[u].header.pNext = ptemp; } } //找出到源点距离最小的顶点 Vertex FindMinIndex(Table T[], int n) { ; int min = Infinity; Vertex min_index = NotVertex; ; i <= n; i++) { if (!T[i].known && T[i].dist < min) { min = T[i].dist; min_index = i; } } return min_index; } //下面是算法关键步骤啦 dijkstra算法 void Dijkstra(Table T[], int n, Vertex source)//source源点 顶点数n { ; T[source].dist = ;//源点到源点的距离为0 T[source].known = true;//源点已知 //在做循环处理前 还要赋值给能直接到达源点的顶点的dist数据 VerNode * ptemp;//能直接到达源点的顶点 ptemp = T[source].header.pNext; Vertex w; while (ptemp) { w = ptemp->ver; T[w].dist = ptemp->weight; T[w].path = source; ptemp = ptemp->pNext; } Vertex v; //处理n-1个顶点 ; i <= n-;i++) { //找出到源点距离最小的顶点 v = FindMinIndex(T, n); if (v == NotVertex) break; T[v].known = true; ptemp = T[v].header.pNext;//找出顶点V所能到的顶点看是否能跟新他们的dist while (ptemp) { w = ptemp->ver; if (!T[w].known && T[w].dist > ptemp->weight + T[v].dist)//进行跟新操作 { T[w].dist = ptemp->weight + T[v].dist; T[w].path = v; } ptemp = ptemp->pNext; } } } //下面输出我们的最短路径吧 void PrintPath(Table T[],Vertex v) { if (T[v].path != NotVertex) { PrintPath(T, T[v].path); cout << " ---> "; } cout << v; } int main() { Vertex v; InitTable(T, , ); Dijkstra(T, , ); cout << "源点1到各个顶点的最短路径如下:" << endl; ; v <= ; v++) { PrintPath(T, v); cout << endl; } system("pause"); ; }
运行结果
需要其他的信息可以根据需要输出
修改补充后的:SakuraOne Dijkstra单源最短路径算法
THOUGHTS
算法思想好理解 实现的话也挺好理解 但是关键就是理解的程度
学习嘛 就是不断重复的过程 对想想就对了还有多动手画画
Dijkstra——单源最短路径的更多相关文章
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- Dijkstra单源最短路径,POJ(2387)
题目链接:http://poj.org/problem?id=2387 Dijkstra算法: //求某一点(源点)到另一点的最短路,算法其实也和源点到所有点的时间复杂度一样,O(n^2); 图G(V ...
- 【模板 && 拓扑】 Dijkstra 单源最短路径算法
话不多说上代码 链式前向星233 #include<bits/stdc++.h> using namespace std; ,_max=0x3fffffff; //链式前向星 struct ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
- 单源最短路径算法---Dijkstra
Dijkstra算法树解决有向图G=(V,E)上带权的单源最短路径问题,但是要求所有边的权值非负. 解题思路: V表示有向图的所有顶点集合,S表示那么一些顶点结合,从源点s到该集合中的顶点的最终最短路 ...
- Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 32824 Accepted: 11098 Description Bes ...
- 单源最短路径——dijkstra算法
dijkstra算法与prim算法的区别 1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...
- 【转】Dijkstra算法(单源最短路径)
原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路 ...
- 图论(四)------非负权有向图的单源最短路径问题,Dijkstra算法
Dijkstra算法解决了有向图G=(V,E)上带权的单源最短路径问题,但要求所有边的权值非负. Dijkstra算法是贪婪算法的一个很好的例子.设置一顶点集合S,从源点s到集合中的顶点的最终最短路径 ...
随机推荐
- jtag、在线仿真器
指令集模拟器 1.部分集成开发环境提供了指令集模拟器,可方便用户在PC机上完成一部分简单的调试工作,但是由于指令集模拟器与真实的硬件环境相差很大,因此即使用户使用指令集模拟器调试通过的程序也有可能无法 ...
- EFLinq查询
1.无参数查询var model = db.Database.SqlQuery<UserInfo>("select* from UserInfoes ").ToList ...
- python sort()方法
https://www.cnblogs.com/whaben/p/6495702.html https://www.cnblogs.com/sunny3312/p/6260472.html
- 启动eclipse could not create the java Vittual Machine
查询并几种方法: 1.都说是 eclipse.ini 环境初始文件的内存问题,续增大堆内存大小,具体配置如,如果找不到问题所在可以试试(该方法是确定环境变量没问题下试行) -Xms64m-Xmx25 ...
- 初识Java Servlet
Java Servlet是什么? Servlet的本质就是一个Java接口,之所以能生成动态的Web内容,是因为对客户的一个HTTP请求,Servlet通过接口这个规范重写了其中的方法,然后Web服务 ...
- Android NDK学习(五):Java调用Native代码流程总结
编写一个Java类,并且在某个方法签名的修饰符中加上native修饰符. 使用Javac命令编译第一步中的Java类,使之成为一个class文件. 使用Javah -jni 包名.类名 生成Jni接口 ...
- VMware虚拟机磁盘操作占用过高问题
使用虚拟机运行Linux图形桌面时,经常因为一个网页或者编译某个程序就导致虚拟机卡死,甚至影响主机使用.明明主机内存有8G,分配给虚拟机的内存也不少,为什么就这么卡顿.打开主机上的任务管理器查看发现磁 ...
- Python学习笔记【第六篇】:迭代器、生成器、高阶函数、装饰器
迭代器 迭代器是访问集合元素的一种方式,迭代器从对象的第一个元素开始访问,知道所有元素被访问完成.迭代器只能往前访问,不能通过索引访问. 类型内部使用__iter__()方法转为迭代器,使用__nex ...
- 一篇文章读懂HTTPS及其背后的加密原理
HTTPS(全称: Hypertext Transfer Protocol Secure,超文本传输安全协议),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.本文,就来深入介绍下其原理. 1 ...
- MyBatis 一级缓存和二级缓存及ehcache整合
一级缓存 什么是缓存?? 缓存是存储在内存(cache)中的数据,一般情况都存在内存,在内存数据存储满了,会存储到硬盘上(disk),或是在我们进行一些操作和配置也可以把缓存存储到磁盘中. 缓存的作用 ...