重复造轮子系列--dijkstra算法
前年一时脑热(理想很丰满,现实很骨感),写了这个最短路径优先的低效版本,且留着回忆吧。
spf.h
#ifndef SPF_H_
#define SPF_H_ typedef struct {
int length;
char src;
char dst;
char prev_hop;
} dijkstra; #define MAX 1024
#define NODE_NUM 5
#define TRUE 1
#define FALSE 0 #endif
spf.c
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <sys/timeb.h>
#include "spf.h" dijkstra DIJK[NODE_NUM][NODE_NUM] = {};
char NODES[NODE_NUM] = {'A', 'B', 'C', 'D', 'E'};
int P_NDS[NODE_NUM] = {};
int U_NDS[NODE_NUM] = {}; int distance(char src, char dst);
void debug(char* fmt,...);
void spf_dijkstra_init();
void spf_show_dijkstra_matrix(int top);
dijkstra* spf_shortest_path_cost(char src, char dst);
void spf_main(int src_top);
int in_pnd_sets(char src);
void spf_pu_sets_init();
int spf_find_candidate_node(int src_top, int top);
int spf_calc_next_hop(int src_top, int top, int min_idx);
void time_show(); int main(int argc, char **argv) {
int i;
//time_show();
spf_dijkstra_init();
for (i=; i<NODE_NUM; i++) {
spf_pu_sets_init();
spf_main(i);
//spf_show_dijkstra_matrix(i);
}
//time_show();
return ;
} void spf_pu_sets_init() {
memset(P_NDS, , sizeof(P_NDS));
memset(U_NDS, , sizeof(U_NDS));
} void spf_main(int src_top) {
int top = src_top;
int min_node_id = -;
int loop = ; if (top >= NODE_NUM || top < ) {
debug("input error src_top = %d, input again plz \n");
return;
} P_NDS[top] = TRUE;
while(TRUE) {
if (loop == NODE_NUM) break;
loop++; min_node_id = spf_find_candidate_node(src_top, top);
if (min_node_id == -) continue;
top = spf_calc_next_hop(src_top, top, min_node_id);
if (top< || top>NODE_NUM) continue;
P_NDS[top] = TRUE;
}
return;
} int spf_find_candidate_node(int src_top, int top) {
int min_idx = -;
int min_cost = MAX; for (int i=; i<NODE_NUM; i++) {
if (TRUE == P_NDS[i]) continue; // 已经计算过路由的就不在计算 int d1 = distance(NODES[top], NODES[i]);
if (MAX == d1 || == d1) continue; U_NDS[i] = TRUE;
dijkstra* dij_dst = spf_shortest_path_cost(NODES[src_top], NODES[i]);
dijkstra* dij_hop = spf_shortest_path_cost(NODES[src_top], NODES[top]); if (NULL == dij_dst || NULL == dij_hop) continue; // 如果源顶点与当前节点的距离 > 源顶点与当前顶点的距离 + 当前顶点与当前节点的距离,
// 则设置当前顶点为当前节点的上一跳节点
// 'S' 表示没有设置过上一跳节点
if (dij_dst->length > d1+dij_hop->length || dij_dst->prev_hop == 'S') {
dij_dst->prev_hop = NODES[top];
} if (d1 < min_cost) {
min_cost = d1;
min_idx = i;
}
} return min_idx;
} int spf_calc_next_hop(int src_top, int top, int min_idx) {
for (int i=; i<NODE_NUM; i++) {
if (FALSE == U_NDS[i]) continue;
int d1 = distance(NODES[src_top], NODES[i]);
int d2 = distance(NODES[top], NODES[i]); if ( == d2) continue;
dijkstra* dij_top = spf_shortest_path_cost(NODES[src_top], NODES[top]);
int d3 = d2 + dij_top->length;
dijkstra* dij_dst = spf_shortest_path_cost(NODES[src_top], NODES[i]);
if (!dij_dst) continue; // 如果源顶点到当前节点的已经过计算的最短路径距离小于直接计算源顶点与当前节点距离
//,则使用最短路径距离
if (dij_dst->length < d1) d1 = dij_dst->length; // 如果源顶点与当前顶点的距离+当前顶点到当前节点的距离
// 小于直接计算源顶点与当前节点距离,
// 则把当前顶点设置为当前的节点上一跳
if ( < d3 && d3 < MAX && d3 <= d1) {
dij_dst->prev_hop = NODES[top];
dij_dst->length = d3;
U_NDS[i] = FALSE;
}
// 如果当前节点的最短路径距离小于当前顶点计算的距离,
// 则调整当前节点上一跳,重新开始最短路由运算
else if (d1 > && d1 < d3 && d3 < MAX) {
int d = distance(dij_dst->src, dij_dst->dst);
// 如果源顶点与目标节点是直连,并且距离小于最短路径距离,
// 则设置上一条节点为源顶点
if (MAX!=d && d<dij_dst->length)
dij_dst->prev_hop = dij_dst->src; P_NDS[top] = FALSE;
U_NDS[top] = TRUE;
min_idx = i;
}
}
return min_idx;
} int in_pnd_sets(char src) {
int i;
for (i=; i<NODE_NUM; i++)
if (NODES[i] == src && P_NDS[i] == TRUE)
return TRUE;
return FALSE;
} void spf_dijkstra_init() {
int i,j;
for (i=; i<NODE_NUM; i++) {
for (j=; j<NODE_NUM; j++) {
DIJK[i][j].length = distance(NODES[i], NODES[j]);
DIJK[i][j].src = NODES[i];
DIJK[i][j].dst = NODES[j];
DIJK[i][j].prev_hop = DIJK[i][j].length == ? NODES[i] : 'S';
}
}
return;
} void spf_show_dijkstra_matrix(int top) {
int i,j;
for (i=; i<NODE_NUM; i++) {
for (j=; j<NODE_NUM; j++) {
if (top == i && DIJK[i][j].src != DIJK[i][j].dst)
printf("len=%d src=%c dst=%c prev=%c\n",
DIJK[i][j].length, DIJK[i][j].src,
DIJK[i][j].dst, DIJK[i][j].prev_hop);
}
}
printf("\n");
return;
} dijkstra* spf_shortest_path_cost(char src, char dst) {
dijkstra* dij = &DIJK[][];
for (int k=; k<NODE_NUM*NODE_NUM; k++,dij++) {
if (dij->src == src && dij->dst == dst)
return dij;
} return NULL;
} int distance(char src, char dst) {
if (src == dst) return ;
if ('A' == src && 'B' == dst) return ;
if ('B' == src && 'A' == dst) return ;
if ('A' == src && 'C' == dst) return ;
if ('C' == src && 'A' == dst) return ;
if ('B' == src && 'D' == dst) return ;
if ('D' == src && 'B' == dst) return ;
if ('B' == src && 'E' == dst) return ;
if ('E' == src && 'B' == dst) return ;
if ('C' == src && 'E' == dst) return ;
if ('E' == src && 'C' == dst) return ;
if ('D' == src && 'E' == dst) return ;
if ('E' == src && 'D' == dst) return ;
return MAX;
}
重复造轮子系列--dijkstra算法的更多相关文章
- 重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关
重复造轮子系列——基于Ocelot实现类似支付宝接口模式的网关 引言 重复造轮子系列是自己平时的一些总结.有的轮子依赖社区提供的轮子为基础,这里把使用过程的一些觉得有意思的做个分享.有些思路或者方法在 ...
- 重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印
重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端 ...
- 重复造轮子系列--内存池(C语言)
这个代码是我上个公司工作项目的里面内存管理(基于伙伴算法)的一个简化又简化的版本. 因为没有内存边界检查: 因为没有内存使用统计: 因为没有考虑线程安全: 因为没有内存分配操作的具体文件位置信息: 因 ...
- 重复造轮子之RSA算法(一) 大素数生成
出于无聊, 打算从头实现一遍RSA算法 第一步, 大素数生成 Java的BigInteger里, 有个现成的方法 public static BigInteger probablePrime(int ...
- 重复造轮子系列--字符串处理(C语言)
这些字符代码是以前写的,源于很久很久以前的一个VC++项目,在当时的部门编程比赛里因为用了项目代码的xsplit函数,万万没想到,那个做了几年的项目里面居然有坑..xsplit函数居然不能split连 ...
- Meteva——让预报检验不再重复造轮子
更多精彩,请点击上方蓝字关注我们! 检验是什么?****预报准确率的客观表达 说到天气预报,你最先会想到什么? 早上听了预报,带了一天伞却没下一滴雨的调侃? 还是 "蓝天白云晴空万里突然暴风 ...
- 避免重复造轮子的UI自动化测试框架开发
一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览 ...
- GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。
1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便 ...
- 第27篇 重复造轮子---模拟IIS服务器
在写程序的时候,重复造轮子是程序员的一个大忌,很多人对重复造轮子持有反对的态度,但是我觉得这个造轮子的过程,是对于现有的知识的一个深入的探索的过程,虽然我们不可能把轮子造的那么的完善,对于现在有的东西 ...
随机推荐
- javaWeb基础 javascript bom5个对象
bom 也称为浏览器对象 browser object model(浏览器对象模型),由五个对象组成: Window:浏览器窗口 最顶层对象. Navigator :浏览器对 ...
- NodeJS基础入门
1.前端最主流的JavaScript运行环境 1>Node.js是一个基于Chrome V8引擎的JavaScript运行环境. 2>Node.js使用了一个事件驱动.非阻塞式I/O的模型 ...
- 获取Grid后台动态添加的子项
例:Grid的子项是包含边框的复选框CheckBox //遍历Grid中的子项 foreach (var c in this.grid_box.Children) { Border bd = c as ...
- int ,long long 范围
类型名称 字节数 取值范围signed char 1 -128-+127short int 2 -32768-+32767int 4 -2147483648-+2147483647(10位数 2^31 ...
- BZOJ3884: 上帝与集合的正确用法(欧拉函数 扩展欧拉定理)
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 3860 Solved: 1751[Submit][Status][Discuss] Descripti ...
- Spring 中IOC(控制反转)&& 通过SET方式为属性注入值 && Spring表达式
### 1. Spring IoC IoC:Inversion of control:控制反转:在传统开发模式下,对象的创建过程和管理过程都是由开发者通过Java程序来实现的,操作权在开发者的Java ...
- JS - 属性描述符各配置的默认值的注意事项
通过字面量或者obj.x = 1;创建的属性 与 通过Object.defineProperty创建的属性,他们的属性描述符的默认值是不同的,前者都为true,后者都为false.
- MySQL另类的备份恢复方法——innodb可传输表空间
Preface There're many ways in backing up or migrating data from one server to another one.Lo ...
- shell脚本结构化语句
本文中记录一下shell中的两种循环语句:for和while for循环 for循环是linux shell中最常用的结构,for循环有三种结构:1.列表for循环.2.不带列表for循环.3.C风格 ...
- Sublime Text3的快捷键和插件
今天重装了一下Sublime Text3,发现了一个不错的网站,关于Sublime Text3的插件安装介绍的很详细,还有右键增强菜单和浏览器打开快捷键的创建.奉上链接 http://www.cnbl ...