shortest path 实现

使用python内置函数直接实现Dij算法,每次用全部已包含集中的点进行计算:

def Dij(start):
    list_a = [1,2,3,4,5,6,7,8,9,10] ##所有点的集合
    list_s = [start]  ##最短路径已经确定的点的集合s
    dist = {} ##最后的结果,存为一个dictionary,key是点的数字,value是从start出发最短的距离
    dist[start] = 0 
    while True:
        if len(list_s) == 10: 
            return dist
        temp = {} ##临时字典,记录所有从s出发右边可以用一条边连接的点
        for i in list_s:
            for j in list(set(list_a)-set(list_s)):
                if map[i][j] >= 0:
                    temp[(dist[i]+map[i][j])] = [i,j] ##记录点的临时最短距离,为s中的点的最短距离加上该边的距离
        dist[temp[min(temp)][1]] = min(temp) ##挑选其中临时最短距离最小的一个点加入s,其临时最短距离就是其真实的最短距离
        patch[temp[min(temp)][1]] = temp[min(temp)][0] ##记录最短路径具体经过的点
        list_s.append(temp[min(temp)][1]) ##挑选其中临时最短距离最小的一个点加入s

               
if __name__ == '__main__':
    map=[[],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        ]
    map[1][2] = 40
    map[1][3] = 8
    map[1][4] = 10
    map[2][7] = 10
    map[2][5] = 6
    map[3][2] = 4
    map[3][4] = 12
    map[3][6] = 2
    map[4][6] = 1
    map[5][3] = 2
    map[5][6] = 2
    map[5][7] = 4
    map[6][8] = 4
    map[6][9] = 3
    map[7][8] = 20
    map[7][10] = 1
    map[8][5] = 0
    map[8][10] = 20
    map[9][4] = 6
    map[9][8] = 10
    map[9][10] = 2
    patch={}
    Dij(1)

使用data_structure课中的,每次用结点进行搜索,并不断更新dist的步骤:


Python实现代码:

def Dij(start):
    list_a = [1,2,3,4,5,6,7,8,9,10]
    list_s = [start]  
    dist = [[],100,100,100,100,100,100,100,100,100,100]
    dist[start] = 0 ##初始化最短距离,起点设为0,和起点有边连接的设为该边数值,其余点设为无穷大(此处为100)
    for j1 in list_a: 
        if map[start][j1] >= 0:
            dist[j1] = map[start][j1]
    while True:
        if len(list_s) == 10: ##终止条件
            return dist
        temp ={}
        for j2 in list(set(list_a)-set(list_s)): ##未收录在s集合中的点中dist最小的点V
              temp[dist[j2]] = j2
        V = temp[min(temp)]
        list_s.append(V) ##将V加入s中
        for j3 in list(set(list_a)-set(list_s)): ##更新所有未收录在s集中的点的dist
            if map[V][j3] >= 0:
                if dist[V] + map[V][j3] < dist[j3]:
                    dist[j3] = dist[V] + map[V][j3]
                    path[j3] = V
                    

现在考虑解决任意起点终点的最短路径问题,用floyd算法:


每次迭代计算只经过编号小于k的定点的路径

其Python的代码实现为:

def floyd():
    ## 初始化时没有边直接相连的点之间最短距离需要设置成无穷大,此处为100
    P = map
    D = map
    for i1 in range(1,11):
        for j1 in range(1,11):
            if i1 == j1:
                D[i1][j1] = 0
            if map[i1][j1] == -1 :
                D[i1][j1] = 100
    for k in range(1,11):
        for i2 in range(1,11):
            for j2 in range(1,11):
                if D[i2][k]+D[k][j2] < D[i2][j2]:
                    D[i2][j2] = D[i2][k]+D[k][j2]
    return D
    
    
    
if __name__ == '__main__':
    map=[[],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
         [[],-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
        ]
    map[1][2] = 40
    map[1][3] = 8
    map[1][4] = 10
    map[2][7] = 10
    map[2][5] = 6
    map[3][2] = 4
    map[3][4] = 12
    map[3][6] = 2
    map[4][6] = 1
    map[5][3] = 2
    map[5][6] = 2
    map[5][7] = 4
    map[6][8] = 4
    map[6][9] = 3
    map[7][8] = 20
    map[7][10] = 1
    map[8][5] = 0
    map[8][10] = 20
    map[9][4] = 6
    map[9][8] = 10
    map[9][10] = 2
    result = floyd()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值