最短路径算法
来源:互联网 发布:华为办公网络 编辑:程序博客网 时间:2024/06/07 05:56
1 Dijkstra算法
(1)确定S集与V集;
(2)找到V集中权值最小的一个Pk,并将其从V集中移入S集;
(3)以Pk为中间点,更新V集中的所有权值;
(4)重复(2)(3);结束条件为V集为空
缺陷:对于有向图和带负权的图就没有用了。
#include <stdio.h>#define NODE_COUNT 6struct Node{#define VSET 0#define SSET 1 int type; int weight;}all[NODE_COUNT];#define INF 0xfffffffint maps[NODE_COUNT][NODE_COUNT] = { { 0, 7, 9, INF, INF, 14 }, { 7, 0, 10, 15, INF, INF }, { 9, 10, 0, 11, INF, 2 }, { INF, 15, 11, 0, 6, INF }, { INF, INF, INF, 6, 0, 9 }, { 14, INF, 2, INF, 9, 0 }};void initset(int src){ int i = 0; for (i = 0; i < NODE_COUNT; i++){ all[i].type = VSET; all[i].weight = maps[src][i]; }}int getvmin(void){ int i = 0, min = INF,sel = -1; for (i = 0; i < NODE_COUNT; i++){ if (all[i].type == VSET){ if (min > all[i].weight){ min = all[i].weight; sel = i; } } } return sel;}int dijkstra(int src){ int sel = 0,i; // (1) 初始化S集V集,刚开始我们将所有集合定位V集 initset(src); // (2) 找到V集中权值最小的一个Pk // (4) 判断V集中是否为空 while ((sel=getvmin()) != -1) { // (2) 将选择的Pk移入S集中 all[sel].type = SSET; // (3) 以Pk为中间点,更新V集中的所有权值 for (i = 0; i < NODE_COUNT; i++){ if (all[i].type == VSET && maps[sel][i] != INF){ if (all[sel].weight + maps[sel][i] < all[i].weight) all[i].weight = all[sel].weight + maps[sel][i]; } } }}void main(void){ int i = 0; dijkstra(0); for (i = 0; i < NODE_COUNT; i++) printf("%d:::%d\n",i,all[i].weight);}
2 Floyd算法
起始点为i,终止点为j,中间点为k,顶点格式N;
(1)确定一个中间点k
(2)更新所有i->j的权值
可用于计算有向图和带负权的图
#include <stdio.h>#define NODE_COUNT 6#define INF 0xffffffint maps[NODE_COUNT][NODE_COUNT] = { { 0, 7, 9, INF, INF, 14 }, { 7, 0, 10, 15, INF, INF }, { 9, 10, 0, 11, INF, 2 }, { INF, 15, 11, 0, 6, INF }, { INF, INF, INF, 6, 0, 9 }, { 14, INF, 2, INF, 9, 0 }};void floyd(int src){ int i = src, j, k,weight; // (1)确定中间点k for (k = 0; k < NODE_COUNT; k++){ //for (i = 0; i < NODE_COUNT; i++){ // (2)更新i->j的权值 for (j = 0; j < NODE_COUNT; j++){ if (maps[i][k] != INF && maps[k][j] != INF){ weight = maps[i][k] + maps[k][j]; if (maps[i][j] > weight){ maps[i][j] = weight; } } } //} }}void main(void){ int i = 0,j = 0; floyd(0); for (i = 0; i < NODE_COUNT; i++) printf("%d:::%d\n", i, maps[0][i]);}
但是有时候我们需要知道该最短路径怎么办呢?
我们需要将第二步细化:(2)更新所有i->j的权值
这里我们加入一个记录路径的变量path;再(1)之前我们需要对path进行初始化;
调整后的算法流程为:
(1)初始化path,将INF全部设为不能走通的路径;可走通的话就讲其前驱记下;比如:
(2)确定一个中间点k
(3)更新所有i->j的权值,同时更新路径
更新后的算法程序为:
void floyd(int src){ int i , j, k,weight; for (i = 0; i < NODE_COUNT; i++){ for (j = 0; j < NODE_COUNT; j++){ if (maps[i][j] == INF) path[i][j] = -1;//表示 i -> j 不通 else path[i][j] = i;// 表示 i -> j 前驱为 i } } // 只求第src个点到各个点的最短路径 i = src; // (1)确定中间点k for (k = 0; k < NODE_COUNT; k++){ //for (i = 0; i < NODE_COUNT; i++){ // (2)更新i->j的权值 for (j = 0; j < NODE_COUNT; j++){ if (maps[i][k] != INF && maps[k][j] != INF){ // 更新权值 weight = maps[i][k] + maps[k][j]; if (maps[i][j] > weight){ maps[i][j] = weight; // 更新路径 path[i][j] = k; //path[i][j] = path[k][j]; } } } //} }}
打印路径输出结果:
int from = 0, to = 3; printf("%d",to); while (path[from][to] != from) { printf("<-%d",path[from][to]); to = path[from][to]; } printf("<-%d",from); printf("\n");
输出结果为倒序输出。
0 0
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- 最短路径算法
- PHP获取多个checkbox的值
- poj 1287 Networking (最小生成树)
- 百度echarts 的使用
- Building Android Kernel for the Nexus 5 — AOSP(6.0.1)
- 淘宝notify-消息中间件(2)
- 最短路径算法
- Pixhawk 四旋翼状态估计
- hdu1711 Number Sequence 求模式串在主串中的位置
- servlet 生命周期 和 作原理详解
- UE4 引擎 package 可执行文件过程中碰到fatal error的常见解决方法
- .gitignore & git rm 从仓库中删去某个文件
- org.apache.jasper.JasperException
- 阿里云服务器配置VPN详解
- Mybatis的<where><foreach><set>等标签详解