数据结构_Floyd算法_python/c实例
overview:
the dynamic programming idea:
there,according to what your number count from(0/1)
if you from 1 to count ,the k<=n
else k<=n-1;
pseudocode:
exmaple input:
python code:
#让算法运行上述图的矩阵表示输入(本程序使用logging包调试,并且使用python3.8的f-string 字符串格式输出 import numpy as np import math import logging as l # l.basicConfig(level=l.DEBUG) inf = math.inf def floyd(d): ''' the d is a graph table(n*n) ''' n = len(d) precursor_table = [[None for i in range(n)] for j in range(n)] for i in range(n): for j in range(n): if i == j: continue if d[i][j] != inf: precursor_table[i][j] = i # print_matrix(precursor_table) # print("pre 0\n", np.array(precursor_table)) l.debug(f'd:{d}') '''d[i][j] means that weight of a shortest path from i to j with intermediate vertices belonging to the set {1, 2, …, k}. Okay to omit superscripts, since extra relaxations can’t hurt.''' # # the k is the intermediate vertices' max numbers(upper bound)(number system)(not the size of the intermediate nodes points ). for k in range(n): ''' traverse the weight matrix in each level subproblem(indicated by k) ''' # the i is the start node of the path(i,j) for i in range(n): # the j is the end node of the path(i,j) for j in range(n): l.debug(f'i,j={i,j}') # the classic relax operation: if d[i][j] > d[i][k]+d[k][j]: d[i][j] = d[i][k]+d[k][j] precursor_table[i][j] = precursor_table[k][j] # print("pre", k+1, "\n", np.array(precursor_table)) return precursor_table d = [ [0, 3, 8, inf, -4], [inf, 0, inf, 1, 7], [inf, 4, 0, inf, inf], [2, inf, -5, 0, inf], [inf, inf, inf, 6, 0] ] def print_matrix(d): for line in d: print(line) ''' 调用floyd算法计算矩阵d(并将保存结果保存在d) (但函数返回值我设置为前驱矩阵)''' precursor_table=floyd(d) print_matrix(d) def print_precurcer(precursor_table,i,j): ''' from 0 count the index of the matrix and from 0 number the node in the graph ''' precursor=precursor_table[i][j] # print(np.array(precursor_table).shape) # print((i,j)) l.debug(f'i,j={i,j}') # print(f'i,j={i,j}') if i==j: # print() print(i,end=" ")#let it break line elif precursor==None: print("no path from",i,"to",j,"exists") else: print_precurcer(precursor_table,i,precursor) print(j,end=" ") ''' 如果是矩阵从1开始计数,那么调用如下函数(直接赋值给print_precurcer函数的引用) ''' def print_precurcer_count_from_1(precursor_table,i,j): precursor=precursor_table[i][j] # print(np.array(precursor_table).shape) # print((i,j)) l.debug(f'i,j={i,j}') # print(f'i,j={i,j}') if i==j: # print() print(i+1,end=" ")#let it break line elif precursor==None: print("no path from",i+1,"to",j+1,"exists") else: print_precurcer(precursor_table,i,precursor) print(j+1,end=" ") # # print_precurcer=print_precurcer_count_from_1 # 打印所有最短路径 def print_paths(precursor_table): n=len(precursor_table) for i in range(n): for j in range(n): print() print(f'i,j={i,j}') print_precurcer(precursor_table,i,j) print() print_paths(precursor_table) # print_precurcer(precursor_table,2,0) ''' 打印最短路径权值矩阵 ''' #print_matrix(d)
相关的理论解释
C code:
#include "stdio.h" #include "stdlib.h" #define MAXVEX 20 #define Infinity 65535 typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */ typedef struct { int vexs[MAXVEX];/*顶点数组*/ int arc[MAXVEX][MAXVEX];/*边数组*/ int numVertexes, numEdges; }MGraph; /*与dijkstra不同,这里用二维数组来记录 但一维也好,二维也罢,在计算机看来都是"一维"的.*/ typedef int Patharc[MAXVEX][MAXVEX]; typedef int ShortPathTable[MAXVEX][MAXVEX]; /* 构建图 */ void CreateMGraph(MGraph* G) { int i, j; /* printf("请输入边数和顶点数:"); */ G->numEdges = 16; G->numVertexes = 9; /*初始化顶点*/ for (i = 0; i < G->numVertexes; i++) { G->vexs[i] = i; } /*初始化边上的权.*/ for (i = 0; i < G->numVertexes; i++) { for (j = 0; j < G->numVertexes; j++) { if (i == j) G->arc[i][j] = 0; else G->arc[i][j] = G->arc[j][i] = Infinity; } } G->arc[0][1] = 1; G->arc[0][2] = 5; G->arc[1][2] = 3; G->arc[1][3] = 7; G->arc[1][4] = 5; G->arc[2][4] = 1; G->arc[2][5] = 7; G->arc[3][4] = 2; G->arc[3][6] = 3; G->arc[4][5] = 3; G->arc[4][6] = 6; G->arc[4][7] = 9; G->arc[5][7] = 5; G->arc[6][7] = 2; G->arc[6][8] = 7; G->arc[7][8] = 4; for (i = 0; i < G->numVertexes; i++) { for (j = i; j < G->numVertexes; j++) { G->arc[j][i] = G->arc[i][j]; } } } /* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */ void ShortestPath_Floyd(MGraph G, Patharc* P, ShortPathTable* D) { int v, w, k; for (v = 0; v < G.numVertexes; ++v) /* 初始化D与P */ { for (w = 0; w < G.numVertexes; ++w) { (*D)[v][w] = G.arc[v][w]; /* D[v][w]值即为对应点间的权值(初始化矩阵) */ (*P)[v][w] = w; /* 初始化P(最短路径序列的中间点(!!!保存各路径的最后一个前驱) */ } } /*核心步骤:*/ for (k = 0; k < G.numVertexes; ++k) /*需要进行G.numBertexes次矩阵迭代/ 第k个矩阵/第k个顶点开放(允许通过.)*/ { /*单个矩阵的迭代需要两重循环:以遍历矩阵的所有位置(比较并迭代所有元素)*/ for (v = 0; v < G.numVertexes; ++v) { for (w = 0; w < G.numVertexes; ++w) { /*min{,}运算(取最/较小者*/ if ((*D)[v][w] > (*D)[v][k] + (*D)[k][w]) {/* 如果经过下标为k的顶点的路径 比 原两点间路径更短 */ (*D)[v][w] = (*D)[v][k] + (*D)[k][w];/* 将 当前 两点间权值 设为更小的一个 */ (*P)[v][w] = (*P)[v][k];/* 路径 设置为经过 下标为k的顶点(在p矩阵的第v行第w列处修改. v->w的中间顶点 修改为终点是k(v->k)使所经过的中间顶点(使之保存v->w 路径上的第一个后继) p数值中,不经过中间顶点(直达时)那第一个后继就是路径的终点*/ /*注意不是:(*P)[v][w] = k 。*/ }//if }//for_111 }//for_11 /*可以在此处监视矩阵的修改情况: printf("允许通过前%d个顶点(0个表示只允许直达)的最短路径P矩阵:\n",k); //printf("0个表示只允许直达\n"); for (v = 0; v < G.numVertexes; ++v) { for (w = 0; w < G.numVertexes; ++w) { printf("%d ", (*P)[v][w]); } printf("\n"); }//for_printf */ }//for_1 } int main(void) { int v, w, k; MGraph G; Patharc P;/*保存v->w路径上的第一个后继;*/ ShortPathTable D; /* 求某点到其余各点的最短路径 */ CreateMGraph(&G); ShortestPath_Floyd(G, &P, &D); printf("各顶点间最短路径如下:\n"); /*三重循环:*/ for (v = 0; v < G.numVertexes; ++v) { for (w = v + 1; w < G.numVertexes; w++) { /*v->w的最短路径*/ printf("v%d-v%d weight: %d ", v, w, D[v][w]); k = P[v][w]; /* 获得第一个路径顶点下标 */ printf(" path: %d", v); /* 打印源点 */ /*顺序打印:*/ /*比较中间点与终点w是否重合*/ while (k != w) /* 如果经过的中间路径顶点下标不是终点(与终点不重合) */ { printf(" -> %d", k); /* 打印途径的路径顶点 (第一个k虽然是最后更新的(如果有的话,当然也可能只在最初几次有被更新,那就可能保持着较小的数值)*/ /*减小规模(更新中间点k),继续判断.*/ k = P[k][w]; /* P[k][w]获得下一个路径顶点下标 */ } printf(" -> %d\n", w); /* 打印终点 */ } printf("\n"); } /*打印两个二维矩阵(类型的变量):D和P*/ printf("最短路径D\n"); for (v = 0; v < G.numVertexes; ++v) { for (w = 0; w < G.numVertexes; ++w) { printf("%d\t", D[v][w]); } printf("\n"); } printf("最短路径P\n"); for (v = 0; v < G.numVertexes; ++v) { for (w = 0; w < G.numVertexes; ++w) { printf("%d ", P[v][w]); } printf("\n"); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2021-10-14 云主机_更换阿里云主机操作系统(图)