Dijkstra算法的原理我就不赘述了,网上有很多博主讲的很好。这是我自己实现的,如有错误望大家指出,一起学习。 基本思路:创建一个表记录是否已经被标记,记录标记点的前一个节点及对应的最短路径。
'''构建连接矩阵''' def connection_matrix(s, e, w): # 连接矩阵的起始、终点及连接边 max_weght = max(set(s).union(set(e))) # 取并集中最大的那个点 df = pd.DataFrame(columns=list(range(max_weght + 1)), index=range(max_weght + 1)).fillna(float("inf")) # 储存点与边权重 for i in range(len(w)): df.loc[s[i], e[i]] = w[i] return df # 连接矩阵 '''找最短路径''' def Dijkstra_shortest_route(start, end, a): # 输入起点、终点,连接矩阵 if start == end: return '%s到%s的最短路径为%s,路径走向为%s' % (start, end, 0, start) # else: df1 = pd.DataFrame(columns=['节点', '是否标记', '值', '前面点'], index=range(len(a))) # 保存标记及值和前点 df1['节点'] = range(len(a)) df1['是否标记'] = 0 # 表示未标记 df1['值'] = float('inf') # 没更新前的值都是inf # 更新第一个点 # df1.loc[start, '是否标记'] = 1 df1.loc[start, '值'] = 0 # 更新结点 while True: min_value = df1[df1['是否标记'] == 0]['值'].idxmin() # 未标记的最小值所在的节点 b = a.columns[a.loc[min_value] < float('inf')] # 某行小于inf所在的列 for i in range(len(b)): # 遍历相邻节点,进行赋值 value = a.loc[min_value, b[i]] # 连接点的边 if value + df1.loc[min_value, '值'] <= df1.loc[b[i], '值']: # 判断,是否修改该节点的值 df1.loc[b[i], '值'] = value + df1.loc[min_value, '值'] df1.loc[b[i], '前面点'] = min_value df1.loc[min_value, '是否标记'] = 1 # 标记该节点,说明已经标记过了 # del a[2] # 标记过的点 if min_value == end: break d = [] front = end while True: d.append(front) front = df1.loc[front, '前面点'] if front == start: d.append(front) break d.reverse() return '%s到%s的最短路径为%s,路径走向为%s' % (start, end, df1.loc[end, '值'], d) # 以list展示路径
测试案例
s = [0, 0, 1, 1, 7, 7, 2, 8, 2, 6, 2, 3, 3, 5] # 源结点 e = [1, 7, 7, 2, 8, 6, 8, 6, 5, 5, 3, 5, 4, 4] # 目的结点 w = [4, 8, 11, 8, 7, 1, 2, 6, 4, 2, 7, 14, 9, 10] # 权 a = connection_matrix(s, e, w) # 数值构建一个连接矩阵 start = 1 end = 5 Dijkstra_shortest_route(start, end, a)