我是(试图)编写Dykstra算法的python实现的学生。我知道这个问题之前已被问过100次了,但我的情况有一些具体细节我还没有完全理解。
我有一个带有10个节点的加权非定向图。我的实际图表将有更多节点。该图表被排序为3维列表。我正在粘贴我们编写的程序的一些输出以生成图形。
`你好。我是(试图)编写Dykstra算法的python实现的学生。我知道这个问题之前已被问过100次了,但我的情况有一些具体细节我还没有完全理解。
我有一个带有10个节点的加权非定向图。我的实际图表将有更多节点。该图表被排序为3维列表。我正在粘贴我们编写的程序的一些输出以生成图形。
Node 1 : [[8, 3], [9, 11], [2, 12], [3, 12], [7, 6]]
Node 2 : [[5, 6], [4, 3], [1, 12], [8, 11], [7, 1]]
Node 3 : [[6, 2], [1, 12], [5, 7], [9, 1]]
Node 4 : [[2, 3], [8, 2], [10, 5], [5, 10], [7, 4]]
Node 5 : [[2, 6], [4, 10], [3, 7], [7, 8]]
Node 6 : [[3, 2], [9, 10]]
Node 7 : [[2, 1], [4, 4], [5, 8], [1, 6], [8, 3]]
Node 8 : [[1, 3], [2, 11], [4, 2], [7, 3], [10, 4]]
Node 9 : [[1, 11], [6, 10], [3, 1]]
Node 10 : [[4, 5], [8, 4]]
在可读性较差的格式中,图表存储为3维列表。因此,例如,在索引0处,存在到节点8,9,2,3和7的连接。节点8和0之间的权重是3.节点0和9之间的权重和11.我认为你得到了这个想法。
myGraph = [[[8,3],[9,11],[2,12],[3,12],[7,6]],[[5,6],[4,3] ,[1,12],[8,11],[7,1]],[[6,2],[1,12],[5,7],[9,1]],[[2, 3],[8,2],[10,5],[5,10],[7,4]],[[2,6],[4,10],[3,7],[7, 8]],[[3,2],[9,10]],[[2,1],[4,4],[5,8],[1,6],[8,3]], [[1,3],[2,11],[4,2],[7,3],[10,4]],[[1,11],[6,10],[3,1] ],[[4,5],[8,4]]]
所以挑战是找到一个dykstra的python实现,它将接受一个列表作为输入,并输出最佳路径。似乎大多数图表是围绕字典数据类型构建的,但这不是我的情况。
我已经开始尝试使用3D列表编写我自己的dijkstra版本,但没有运气,因为它对我来说有点复杂。我也尝试在Python中使用以前发布的dijkstra算法版本,但是它们被设计为运行字典而不是3维列表。这是我早些时候的尝试。
[[[4, 2], [2, 1], [3, 4]], [[1, 1], [4, 2], [3, 4]], [[1, 4], [2, 4],
[4, 4]], [[1, 2], [2, 2], [3, 4]]]
class Graph:
def __init__(self):
self.nodes = set()
self.edges = defaultdict(list)
self.distances = {}
def add_node(self, value):
self.nodes.add(value)
def add_edge(self, from_node, to_node, distance):
self.edges[from_node].append(to_node)
self.edges[to_node].append(from_node)
self.distances[(from_node, to_node)] = distance
def dijsktra(graph, initial):
visited = {initial: 0}
path = {}
nodes = set(graph.nodes)
while nodes:
min_node = None
for node in nodes:
if node in visited:
if min_node is None:
min_node = node
elif visited[node] < visited[min_node]:
min_node = node
if min_node is None:
break
nodes.remove(min_node)
current_weight = visited[min_node]
for edge in graph.edges[min_node]:
weight = current_weight + graph.distance[(min_node, edge)]
if edge not in visited or weight < visited[edge]:
visited[edge] = weight
path[edge] = min_node
return visited, path
我真的非常感谢任何人可以给予我的任何帮助,因为我一直在努力解决这个问题。谢谢!
答案 0 :(得分:0)
尝试可用实现的建议似乎很好,但由于它不是一个复杂的算法,您可以尝试自己的代码。
Dijkstra的简单案例:
如图所示,您将分别在所有节点上运行算法。我们只考虑节点0,你应该有三个数据结构来选择路由&#39;和所有未被访问过的人&#39;并且在之前的迭代中未使用过&#39;。首先检查可以通过简单列表比较或检查实现的邻居,选择成本最低的邻居并将其添加到所选路由,并将未使用的邻居添加为上一次迭代中未使用的邻居。然后转到选定的路径节点,将其邻居与上一次迭代中的邻居进行比较。您将继续此操作,直到您选择的路径结构中的所有节点都可用。
答案 1 :(得分:0)
以下似乎适用于您的数据结构:
initial=1 #This is the number-label (not the index) of your starting node
assigned={} #When a node has been given a permenant min-weight
visited={initial:0} #When a node has a temporary min-weight
path={initial:[initial]} #stores the path after a permenant weight has been assigned
myGraph = [[[8, 3], [9, 11], [2, 12], [3, 12], [7, 6]], [[5, 6], [4, 3], [1, 12], [8, 11], [7, 1]], [[6, 2], [1, 12], [5, 7], [9, 1]], [[2, 3], [8, 2], [10, 5], [5, 10], [7, 4]], [[2, 6], [4, 10], [3, 7], [7, 8]], [[3, 2], [9, 10]], [[2, 1], [4, 4], [5, 8], [1, 6], [8, 3]], [[1, 3], [2, 11], [4, 2], [7, 3], [10, 4]], [[1, 11], [6, 10], [3, 1]], [[4, 5], [8, 4]]]
while len(assigned)<len(myGraph):
next_node= min(visited,key=visited.get)
assigned[next_node]=visited[next_node]
del visited[next_node]
for node in myGraph[next_node-1]: # The minus one is because your nodes are numbered from 1 (as apposed to 0).
if node[0] in visited:
if visited[node[0]]>assigned[next_node]+node[1]:
visited[node[0]]=assigned[next_node]+node[1]
else:
if node[0] in assigned:
if assigned[node[0]]+node[1]==assigned[next_node]:
path[next_node]=path[node[0]]+[next_node]
else:
visited[node[0]]=assigned[next_node]+node[1]
path
是一个包含列表的dict,用于显示从初始节点开始的路径。我会解释每一步,但我想我只是解释Dikstra的算法(你似乎已经知道了) - 如果你有问题,请在评论中要求澄清。我希望这会对你有所帮助。