重复造*系列--dijkstra算法

时间:2022-04-27 06:01:16

前年一时脑热(理想很丰满,现实很骨感),写了这个最短路径优先的低效版本,且留着回忆吧。

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;
}