Python-Floyd算法(五行核心代码)

一、前言

    很早之前就想把之前看过的算法问题总结出来,现在出的书籍基本上都是以C、Java为基础的算法书籍,以Python为基础的算法书籍很少。自己最近在学ML,开始使用Python,相比较与C与Java,Python的代码量更少,代码阅读起来也比较简单,所以打算用Python将以前看过的算法总结一次。这个系列不以难易程度递增更新,想起哪个算法就先更新哪一个。

    在图论中有一个很重要的问题--最短路径问题,最短路径应用方面很广,最早接触这个问题的是因为研究生期间要写一篇关于SDN路径规划论文,需要计算出业务流量在任意两点间传输的最短路径,当时选择了Floyd算法与Dijkstra算法。这次先更新Floyd算法,Dijkstra算法在之后的文章中会写。

二、算法基本介绍

     如下图所示,图中点到点的路径都是单向的,单项箭头线上的数字表示点与点之间的距离。那么任意两点之间的最短路径应该怎么求呢?

                                                 

    首先,我们用一个矩阵来存储上图的信息。上图有四个点,因此我们使用一个4*4的矩阵来存储。

                                                                          

    我们使用d[i][j]来表示任意两点之间的距离,那么上图中d[1][2]=2。d[2][1]为正无穷,则表示点2到点1在不经过第三个点的情况下为不可达。假设一下,如果AB两点之间的距离是固定的,那么我们怎么让这两点之间的距离变短,这时我们会想到引入第三个点C,有人可能会想,再多引入一个点怎么会让距离变的更短,注意,我们这里描述的两点之间的距离并不是直线距离。如下图所示d[A][B]>d[A][C]+d[C][B]。

                                                             

    假设现在只允许经过1号顶点,求任意两点之间的最短距离。如果d[i][1]+d[1][j]<d[i][j],则d[i][j]=d[i][1]+d[1][j]。因此最短路径更新如下,依次类推只允许经过2号顶点。

                                                                       

    

    最后Python的实现代码如下:

for k in range(N):
    for i in range(N):
        for j in range(N):
            if d[i][j] > d[i][k] + d[k][j]:
                d[i][j] = d[i][k] + d[k][j]
三、算法基本应用
    
#/usr/bin/env python
#coding:utf-8
#editor:evan
#time:2018.03.14
import numpy as np

N = 4
M = 100
edge = np.mat([[0,2,6,4],[M,0,3,M],[7,M,0,1],[5,M,12,0]])
A = edge[:]
path = np.zeros((N,N))

def Floyd():
    for i in range(N):
        for j in range(N):
            if(edge[i,j] != M and edge[i,j] != 0):
                path[i][j] = i

    print 'init:'
    print A,'\n',path
    for a in range(N):
        for b in range(N):
            for c in range(N):
                if(A[b,a]+A[a,c]<A[b,c]):
                    A[b,c] = A[b,a] + A[a,c]
                    path[b][c] = path[a][c]

    print 'result:'
    print A,'\n',path

if __name__ == "__main__":
    Floyd()

运行结果如下:

init:
[[  0   2   6   4]
 [100   0   3 100]
 [  7 100   0   1]
 [  5 100  12   0]] 
[[ 0.  0.  0.  0.]
 [ 0.  0.  1.  0.]
 [ 2.  0.  0.  2.]
 [ 3.  0.  3.  0.]]
result:
[[ 0  2  5  4]
 [ 9  0  3  4]
 [ 6  8  0  1]
 [ 5  7 10  0]] 
[[ 0.  0.  1.  0.]
 [ 3.  0.  1.  2.]
 [ 3.  0.  0.  2.]
 [ 3.  0.  1.  0.]]








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值