算法 单源最短路径 dijkstra算法
2021-03-05 14:28
标签:__name__ 结合 start arc == ret splay 矩阵 输出 有向带权图的单源最短路径经典算法是dijkstra,下面就对算法的过程和代码实现进行记录 算法过程: 1、数据结构:图的带权邻接矩阵G.Edge[u][i],如果u到i有边则G.Edge[u][i]等于边的权值;否则G.Edge[u][i]等于∞。 代码实现: 算法 单源最短路径 dijkstra算法 标签:__name__ 结合 start arc == ret splay 矩阵 输出 原文地址:https://www.cnblogs.com/flags-blog/p/14320515.html
一维数组dist[i]记录从起始点到i节点的最短路径长度,一维数组p[i]记录i节点最短路径的前驱
2、初始化:令集合S={u},其中u是起始点,对于V-S集合所有顶点i,初始化dist[i]=G.Edge[u][i],其中集合V是所有顶点的集合。如果i是u的邻接点,初始化p[i]=u,否则p[i]=-1
3、找最小:在集合V-S中按照贪心策略在dist中找出最小值dist[i],则顶点i就是离源点u最近的节点(注意:此处找到的最小i并不一定就是上一步找到节点的邻接点)
4、将找到的i节点加入到s集群,并更新V-S
5、判断是否结束:如果V-S为空则搜索结束,否则到步骤6
6、对结合V-S中与节点i邻接的顶点j,如果有dist[j]>dist[i]+G.Edge[i][j]则dist[j]=dist[i]+G.Edge[i][j];更新p[j]=i,继续执行步骤3#!/usr/bin/env python
# -*- coding:utf-8 -*-
graphNodeList = [] #图存储节点信息
graphAdjMatrix = [] #有向权重图邻接矩阵
searchNodeInfo = [] #djstla最短距离已经遍历的节点
dist = [] #存储最短路径开销
p = [] #djstla最短路径每个顶点的直接前驱
MAX = 100000
#str切分后给列表赋值格式
def acquireNode():
node_list = input("请输入途中所有的点,以空格分隔:")
for nodeInfo in node_list.strip().split(" "):
graphNodeList.append(nodeInfo)
#根据输入信息填写邻接矩阵
def acquireSideUndig():
print("请输入图的所有边信息,格式为边的两个顶点,使用空格分隔。 eg:a b,如果全部信息输入完毕请输入end")
while True:
tempSide = input(">:")
if tempSide.strip().lower() == "end":
print("输入结束")
break
tempNodeList = tempSide.strip().split(" ")
if len(tempNodeList) == 2:
if tempNodeList[0] in graphNodeList and tempNodeList[1] in graphNodeList:
createUndigraphAdjMatrix(tempNodeList[0], tempNodeList[1])
else:
print("边信息输入有误,请重新输入")
continue
else:
print("输入有误请重新输入")
continue
def acquireSideDig():
print("请输入图的所有边信息,格式为边的两个顶点,使用空格分隔。 eg:a b,如果全部信息输入完毕请输入end")
while True:
tempSide = input(">:")
if tempSide.strip().lower() == "end":
print("输入结束")
break
tempNodeList = tempSide.strip().split(" ")
if len(tempNodeList) == 2:
if tempNodeList[0] in graphNodeList and tempNodeList[1] in graphNodeList:
createDigraphAdjMatrix(tempNodeList[0], tempNodeList[1])
else:
print("边信息输入有误,请重新输入")
continue
else:
print("输入有误请重新输入")
continue
def acquireSideDigWeight():
print("请输入图的所有边信息,格式为边的两个顶点和权重,使用空格分隔。 eg:a b weight,如果全部信息输入完毕请输入end")
while True:
tempSide = input(">:")
if tempSide.strip().lower() == "end":
print("输入结束")
break
tempNodeList = tempSide.strip().split(" ")
if len(tempNodeList) == 3:
if tempNodeList[0] in graphNodeList and tempNodeList[1] in graphNodeList:
createDigraphAdjMatrixWeight(tempNodeList[0], tempNodeList[1], int(tempNodeList[2]))
else:
print("边信息输入有误,请重新输入")
continue
else:
print("输入有误请重新输入")
continue
#初始化邻接矩阵;注意多维数组初始化格式以及数据的浅拷贝坑
def initGraphAdjMatrixWeight(nodeNum):
for row in range(nodeNum):
tempList = []
for column in range(nodeNum):
tempList.append(MAX)
graphAdjMatrix.append(tempList)
#根据输入顶点信息完成邻接表
def createUndigraphAdjMatrix(node0, node1):
tempIndex1 = graphNodeList.index(node0)
tempIndex2 = graphNodeList.index(node1)
graphAdjMatrix[tempIndex1][tempIndex2] = 1
graphAdjMatrix[tempIndex2][tempIndex1] = 1
def createDigraphAdjMatrix(node0, node1):
tempIndex1 = graphNodeList.index(node0)
tempIndex2 = graphNodeList.index(node1)
graphAdjMatrix[tempIndex1][tempIndex2] = 1
def createDigraphAdjMatrixWeight(node0, node1, weight):
tempIndex1 = graphNodeList.index(node0)
tempIndex2 = graphNodeList.index(node1)
graphAdjMatrix[tempIndex1][tempIndex2] = weight
#pRINT输出空格和换行的写法
def printAdjMatrix(nodeNum):
for row in range(nodeNum):
for column in range(nodeNum):
print(graphAdjMatrix[row][column], end=" ")
print("")
def maindigAdjMatWeight():
acquireNode()
initGraphAdjMatrixWeight(len(graphNodeList))
acquireSideDigWeight()
def dijkstra(startnode):
##初始化
for node in graphNodeList:
# 初始化集合S,在集合S中的点在searchNodeInfo对应位置为True,默认初始化为False
if node == startnode:
searchNodeInfo.append(True)
else:
searchNodeInfo.append(False)
for index, value in enumerate(graphAdjMatrix[graphNodeList.index(startnode)]):
# 初始化前驱列表p;将startnode的邻接点前驱初始化为startnode,否则初始化为-1;初始化最短路径长度dist
dist.append(value)
if value MAX:
p.append(startnode)
else:
p.append(-1)
##将查找最小邻接点和使用最小邻接点更新dist p列表循环n-1次即可将所有数据更新完毕,起点已经是确定
for loop in range(len(graphNodeList)-1):
##找dist中searchpath为False的最小值.
tempdist = []
for index, value in enumerate(searchNodeInfo):
if value is False:
tempdist.append(dist[index])
#根据找到的最小值更新searchPath,判断节点是否查询完成;查询完成程序返回
tempindex = dist.index(sorted(tempdist)[0])
searchNodeInfo[tempindex] = True
if False not in searchNodeInfo:
printdijkstra(startnode)
return 0
#否则使用新加到search的节点更新其邻接点的dist值和p前驱
for index, value in enumerate(graphAdjMatrix[tempindex]):
if searchNodeInfo[index] is False and dist[index] > dist[tempindex] + value:
dist[index] = dist[tempindex] + value
p[index] = graphNodeList[tempindex]
printdijkstra(startnode)
#输出原始节点到其它节点的最短路径长度和路径上的顶点
def printdijkstra(startnode):
for i in range(len(graphNodeList)):
if i == graphNodeList.index(startnode):
print("这是起点自己%s" %startnode)
else:
print("起始点到顶点%s的距离是%d" %(graphNodeList[i], dist[i]),end="。")
print("访问路径为:", end=" ")
temppath = []
temp_pi = i
#找到顶点的所有前驱拼接起来即为最优路径
while True:
if p[temp_pi] != -1:
temppath.append(p[temp_pi])
temp_pi = graphNodeList.index(p[temp_pi])
else:
break
temppath.reverse()
for path in temppath:
print("%s->" % path, end="")
print(graphNodeList[i])
if __name__ == "__main__":
maindigAdjMatWeight()
dijkstra(graphNodeList[0])
上一篇:037.Python的UDP语法
下一篇:python解释器的下载
文章标题:算法 单源最短路径 dijkstra算法
文章链接:http://soscw.com/index.php/essay/60484.html