数据结构_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;
}

在这里插入图片描述

posted @   xuchaoxin1375  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2021-10-14 云主机_更换阿里云主机操作系统(图)
点击右上角即可分享
微信分享提示