重复造轮子系列--dijkstra算法

spf.h

 1 #ifndef SPF_H_
 2 #define SPF_H_
 3
 4
 5 typedef struct {
 6     int length;
 7     char src;
 8     char dst;
 9     char prev_hop;
10 } dijkstra;
11
12 #define MAX 1024
13 #define NODE_NUM 5
14 #define TRUE 1
15 #define FALSE 0
16
17 #endif

spf.c

  1 #include <stdio.h>
  2 #include <stdarg.h>
  3 #include <string.h>
  4 #include <limits.h>
  5 #include <time.h>
  6 #include <sys/timeb.h>
  7 #include "spf.h"
  8
  9 dijkstra DIJK[NODE_NUM][NODE_NUM] = {0};
 10 char NODES[NODE_NUM] = {‘A‘, ‘B‘, ‘C‘, ‘D‘, ‘E‘};
 11 int P_NDS[NODE_NUM] = {0};
 12 int U_NDS[NODE_NUM] = {0};
 13
 14 int distance(char src, char dst);
 15 void debug(char* fmt,...);
 16 void spf_dijkstra_init();
 17 void spf_show_dijkstra_matrix(int top);
 18 dijkstra* spf_shortest_path_cost(char src, char dst);
 19 void spf_main(int src_top);
 20 int in_pnd_sets(char src);
 21 void spf_pu_sets_init();
 22 int spf_find_candidate_node(int src_top, int top);
 23 int spf_calc_next_hop(int src_top, int top, int min_idx);
 24 void time_show();
 25
 26 int main(int argc, char **argv) {
 27     int i;
 28     //time_show();
 29     spf_dijkstra_init();
 30     for (i=0; i<NODE_NUM; i++) {
 31         spf_pu_sets_init();
 32         spf_main(i);
 33         //spf_show_dijkstra_matrix(i);
 34     }
 35     //time_show();
 36     return 0;
 37 }
 38
 39 void spf_pu_sets_init() {
 40     memset(P_NDS, 0, sizeof(P_NDS));
 41     memset(U_NDS, 0, sizeof(U_NDS));
 42 }
 43
 44 void spf_main(int src_top) {
 45     int top = src_top;
 46     int min_node_id = -1;
 47     int loop = 0;
 48
 49     if (top >= NODE_NUM || top < 0) {
 50         debug("input error src_top = %d, input again plz \n");
 51         return;
 52     }
 53
 54     P_NDS[top] = TRUE;
 55     while(TRUE) {
 56         if (loop == NODE_NUM) break;
 57         loop++;
 58
 59         min_node_id = spf_find_candidate_node(src_top, top);
 60         if (min_node_id == -1) continue;
 61         top = spf_calc_next_hop(src_top, top, min_node_id);
 62         if (top<0 || top>NODE_NUM) continue;
 63         P_NDS[top] = TRUE;
 64     }
 65     return;
 66 }
 67
 68 int spf_find_candidate_node(int src_top, int top) {
 69     int min_idx = -1;
 70     int min_cost = MAX;
 71
 72     for (int i=0; i<NODE_NUM; i++) {
 73         if (TRUE == P_NDS[i]) continue;  // 已经计算过路由的就不在计算
 74
 75         int d1 = distance(NODES[top], NODES[i]);
 76         if (MAX == d1 || 0 == d1) continue;
 77
 78         U_NDS[i] = TRUE;
 79         dijkstra* dij_dst = spf_shortest_path_cost(NODES[src_top], NODES[i]);
 80         dijkstra* dij_hop = spf_shortest_path_cost(NODES[src_top], NODES[top]);
 81
 82         if (NULL == dij_dst || NULL == dij_hop) continue;
 83
 84         // 如果源顶点与当前节点的距离 > 源顶点与当前顶点的距离 + 当前顶点与当前节点的距离,
 85         // 则设置当前顶点为当前节点的上一跳节点
 86         // ‘S‘ 表示没有设置过上一跳节点
 87         if (dij_dst->length > d1+dij_hop->length || dij_dst->prev_hop == ‘S‘) {
 88             dij_dst->prev_hop = NODES[top];
 89         }
 90
 91         if (d1 < min_cost) {
 92             min_cost = d1;
 93             min_idx = i;
 94         }
 95     }
 96
 97     return min_idx;
 98 }
 99
100 int spf_calc_next_hop(int src_top, int top, int min_idx) {
101     for (int i=0; i<NODE_NUM; i++) {
102         if (FALSE == U_NDS[i]) continue;
103         int d1 = distance(NODES[src_top], NODES[i]);
104         int d2 = distance(NODES[top], NODES[i]);
105
106         if (0 == d2) continue;
107         dijkstra* dij_top = spf_shortest_path_cost(NODES[src_top], NODES[top]);
108         int d3 = d2 + dij_top->length;
109         dijkstra* dij_dst = spf_shortest_path_cost(NODES[src_top], NODES[i]);
110         if (!dij_dst) continue;
111
112         // 如果源顶点到当前节点的已经过计算的最短路径距离小于直接计算源顶点与当前节点距离
113         //,则使用最短路径距离
114         if (dij_dst->length < d1) d1 = dij_dst->length;
115
116         // 如果源顶点与当前顶点的距离+当前顶点到当前节点的距离
117         // 小于直接计算源顶点与当前节点距离,
118         // 则把当前顶点设置为当前的节点上一跳
119         if (0 < d3 && d3 < MAX && d3 <= d1) {
120             dij_dst->prev_hop = NODES[top];
121             dij_dst->length = d3;
122             U_NDS[i] = FALSE;
123         }
124         // 如果当前节点的最短路径距离小于当前顶点计算的距离,
125         // 则调整当前节点上一跳,重新开始最短路由运算
126         else if (d1 > 0 && d1 < d3 && d3 < MAX) {
127             int d = distance(dij_dst->src, dij_dst->dst);
128             // 如果源顶点与目标节点是直连,并且距离小于最短路径距离,
129             // 则设置上一条节点为源顶点
130             if (MAX!=d && d<dij_dst->length)
131                 dij_dst->prev_hop = dij_dst->src;
132
133             P_NDS[top] = FALSE;
134             U_NDS[top] = TRUE;
135             min_idx = i;
136         }
137     }
138     return min_idx;
139 }
140
141 int in_pnd_sets(char src) {
142     int i;
143     for (i=0; i<NODE_NUM; i++)
144         if (NODES[i] == src && P_NDS[i] == TRUE)
145             return TRUE;
146     return FALSE;
147 }
148
149 void spf_dijkstra_init() {
150     int i,j;
151     for (i=0; i<NODE_NUM; i++) {
152         for (j=0; j<NODE_NUM; j++) {
153             DIJK[i][j].length = distance(NODES[i], NODES[j]);
154             DIJK[i][j].src = NODES[i];
155             DIJK[i][j].dst = NODES[j];
156             DIJK[i][j].prev_hop = DIJK[i][j].length == 0 ? NODES[i] : ‘S‘;
157         }
158     }
159     return;
160 }
161
162 void spf_show_dijkstra_matrix(int top) {
163     int i,j;
164     for (i=0; i<NODE_NUM; i++) {
165         for (j=0; j<NODE_NUM; j++) {
166             if (top == i && DIJK[i][j].src != DIJK[i][j].dst)
167                 printf("len=%d src=%c dst=%c prev=%c\n",
168                 DIJK[i][j].length, DIJK[i][j].src,
169                 DIJK[i][j].dst, DIJK[i][j].prev_hop);
170         }
171     }
172     printf("\n");
173     return;
174 }
175
176 dijkstra* spf_shortest_path_cost(char src, char dst) {
177     dijkstra* dij = &DIJK[0][0];
178     for (int k=0; k<NODE_NUM*NODE_NUM; k++,dij++) {
179         if (dij->src == src && dij->dst == dst)
180             return dij;
181     }
182
183     return NULL;
184 }
185
186 int distance(char src, char dst) {
187     if (src == dst) return 0;
188     if (‘A‘ == src && ‘B‘ == dst) return 1;
189     if (‘B‘ == src && ‘A‘ == dst) return 1;
190     if (‘A‘ == src && ‘C‘ == dst) return 5;
191     if (‘C‘ == src && ‘A‘ == dst) return 5;
192     if (‘B‘ == src && ‘D‘ == dst) return 6;
193     if (‘D‘ == src && ‘B‘ == dst) return 6;
194     if (‘B‘ == src && ‘E‘ == dst) return 2;
195     if (‘E‘ == src && ‘B‘ == dst) return 2;
196     if (‘C‘ == src && ‘E‘ == dst) return 1;
197     if (‘E‘ == src && ‘C‘ == dst) return 1;
198     if (‘D‘ == src && ‘E‘ == dst) return 1;
199     if (‘E‘ == src && ‘D‘ == dst) return 1;
200     return MAX;
201 }
时间: 2024-10-18 00:30:30

重复造轮子系列--dijkstra算法的相关文章

重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印

重复造轮子系列——基于FastReport设计打印模板实现桌面端WPF套打和商超POS高度自适应小票打印 一.引言 桌面端系统经常需要对接各种硬件设备,比如扫描器.读卡器.打印机等. 这里介绍下桌面端系统打印经常使用的场景. 1.一种是类似票务方面的系统需要打印固定格式的票据.比如景点门票.车票.电影票. 这种基本是根据模板调整位置套打. 2.还有一种是交易小票,比如商超POS小票,打印长度会随着内容的大小自动伸缩. 这种就不仅仅是固定格式的套打了,还得计算数据行以适应不同的打印长度. 打印方式

重复造轮子系列--桶排序

理解了基数排序,也就理解了桶排序. 桶排序就是基数排序的一种优化,从MSD开始,即取最高位来排一次序,如果最高位没有重复(意味着没有冲突需要处理),是算法的最佳状态,O(n). 如果有冲突,就将冲突的元素存放到对应的桶里(代码就是一个链表或者数组或者stl容器),然后对每个桶进行一次插入排序,平均情况的话冲突很小的,桶里的元素的数量就不多,速度很快, 如果冲突集中在几个桶甚至一个桶里,那么就出现了算法的最差情形,也就是O(n^2)的复杂度. 下面是例子代码实现: 1 template<typen

重复造轮子系列--计数,基数排序

计数,基数的中文读音都一样,这翻译的人还嫌我们计算机不够乱,真的想吐槽. 不管了,毕竟代码还是不一样的. 1.计数排序(counter sort): 通过一个上限来统计集合里的数值(或者其他非数值类型映射的数值),并累计比小于自己(包括)的数值的统计的个数,从而形成排序的索引(也就是前面有多少个小于我的,我的位置就确定了). 普通计数排序代码:(仍需优化,valuetype默认是整数类型) 1 template<typename _InIt> 2 void counter_sort(_InIt

重复造轮子系列--插入排序和归并排序

囧,道理很简单,实践起来却不容易. 因为编程语言跟算法描述数据结构并不能完全一致,所以理论到实践还是有些出入的. 下面的例子是没有哨兵位置的实现: 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <cassert> 5 6 using namespace std; 7 8 template<typename _InIt, typename _Func

重复造轮子之RSA算法(一) 大素数生成

出于无聊, 打算从头实现一遍RSA算法 第一步, 大素数生成 Java的BigInteger里, 有个现成的方法 public static BigInteger probablePrime(int bitLength, Random rnd) { bitLength是期望生成的素数的二进制位数, rnd是随机数发生器 函数注释表明, 这个方法的返回值为合数的概率为2^-100 生成100个1024位的素数, 耗时13471ms 但是显然我不打算直接使用这个函数, 要做就从最底层做起! 目前的做

重复造轮子系列--内存池(C语言)

mem_pool.h 1 #ifndef MEM_POOL_H_ 2 #define MEM_POOL_H_ 3 4 typedef struct MemBlock { 5 struct MemBlock* next; 6 int size; 7 void *ptr; 8 } MemBlock; 9 10 typedef unsigned char byte; 11 12 // 8 16 32 64 128 256 512 1024 2048 4096 13 // 1 2 4 8 16 32 6

重复造轮子系列--字符串常用操作(C语言)

xstring.h 1 #ifndef XSTRING 2 #define XSTRING 3 4 typedef struct xstring { 5 char *str; 6 struct xstring *next; 7 } xstring; 8 9 10 ////////////////////////////////////////////////////////////////////////// 11 void* allocate(size_t size); 12 13 #ifde

GitHub Android 最火开源项目Top20 GitHub 上的开源项目不胜枚举,越来越多的开源项目正在迁移到GitHub平台上。基于不要重复造轮子的原则,了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目,有时能够让你达到事半功倍的效果。

1. ActionBarSherlock(推荐) ActionBarSherlock应该算得上是GitHub上最火的Android开源项目了,它是一个独立的库,通过一个API和主题,开发者就可以很方便地使用所有版本的Android动作栏的设计模式. 对于Android 4.0及更高版本,ActionBarSherlock可以自动使用本地ActionBar实现,而对于之前没有ActionBar功能的版本,基于Ice Cream Sandwich的自定义动作栏实现将自动围绕布局.能够让开发者轻松开发

避免重复造轮子的UI自动化测试框架开发

一懒起来就好久没更新文章了,其实懒也还是因为忙,今年上半年的加班赶上了去年一年的加班,加班不息啊,好了吐槽完就写写一直打算继续的自动化开发 目前各种UI测试框架层出不穷,但是万变不离其宗,驱动PC浏览器的基本上底层都是selenium,驱动无线app和浏览器基本是appium.monkey之类的,底层都是基于官方支持的自动化测试框架开发而来,然后上层又做了各种封装 首先在开始计划开发自动化时,第一步是了解目前已有的自动化开发技术,上面说了,最底层的就那几种,根据实际要去测试的业务需求选择合适的自