我一直在做学校作业,我需要实现Dijkstra的算法。这本身并不太难,但不幸的是,自动检查脚本不同意我的所有实现(我实际上做了8个不同的版本)。所有初始数据检查都能正常工作,只有当脚本生成随机数据时,才会有所不同。我的路径和脚本的路径具有相同的距离,但路径上的顶点不同。例如:
教师路径:City2,City15,City16,City6,
学生路径:City2,City15,City18,City0,City6,
我甚至联系了那位刚回答“你必须使用优先级队列:-)”的老师,尽管我使用了一个(事实上,从我自己到heapq的几个实现)。我做错了什么或教师脚本是不正确的?我希望代码能够自我评论,足以让人理解。感谢您给我的任何建议。
在源顶点上调用算法,并计算到每个其他连接节点的最短距离和路径。如果顶点具有与已经存在的那些相同的minDistance(即优先级),它应该在它之前,而不是在它之后。
class Node:
"""Basic node of the priority queue"""
def __init__(self, data, priority):
self.data = data
self.nextNode = None
self.priority = priority
self.id = data.id
class PriorityQueue:
"""Basic priority queue with add, remove and update methods"""
def __init__(self):
self.head = None
self.count = 0
def add(self, data, priority):
"""Adds data with priority in the proper place"""
node = Node(data, priority)
if not self.head:
self.head = node
elif node.priority <= self.head.priority:
node.nextNode = self.head
self.head = node
else:
checker = self.head
while True:
if not checker.nextNode or node.priority >= checker.nextNode.priority:
break
checker = checker.nextNode
node.nextNode = checker.nextNode
checker.nextNode = node
return 0
def remove(self, data):
"""Removes specified node and reconnects the remaining nodes, does nothing if node not found"""
checker = self.head
if not self.head:
return 0
if checker.id == data.id:
self.head = checker.nextNode
while True:
checker = checker.nextNode
if not checker or not checker.nextNode:
return 0
if checker.nextNode.id == data.id:
checker.nextNode = checker.nextNode.nextNode
break
return 0
def update(self, data):
"""Updates priority of existing node via removing and re-adding it"""
self.remove(data)
self.add(data, data.minDistance)
return 0
def getMin(self):
"""Returns the minimum priority data"""
min = self.head
return min.data
class Edge:
"""Edge of the graph, contains source, target and weight of line"""
def __init__(self, source, target, weight):
self.source = source
self.target = target
self.weight = weight
class Vertex:
"""Vertex of the graph, everything except id and name is filled later"""
def __init__(self, id, name):
self.id = id
self.name = name
self.minDistance = float('inf')
self.previousVertex = None
self.edges = []
self.visited = False
class Dijkstra:
"""Dijkstra's algorithm implementation"""
def __init__(self):
self.vertexes = []
self.nodes = {}
self.unvisited = PriorityQueue()
def createGraph(self, vertexes, edgesToVertexes):
"""Connects edges to appropriate vertexes, adds vertexes to node dictionary"""
self.vertexes = vertexes
for vertex in self.vertexes:
for edge in edgesToVertexes:
if vertex.id == edge.source:
vertex.edges.append(edge)
edgesToVertexes.remove(edge)
self.nodes[vertex.id] = vertex
return 0
def getVertexes(self):
"""Returns vertexes in graph, should be called after creating it just to check"""
return self.vertexes
def computePath(self, sourceId):
"""Fills in minDistance and previousVertex of all nodes from source"""
mainNode = self.nodes[sourceId]
mainNode.minDistance = 0
self.unvisited.add(mainNode, 0)
while self.unvisited.head:
mainNode = self.unvisited.getMin()
mainNode.visited=True
for edge in mainNode.edges:
tempDistance = mainNode.minDistance + edge.weight
targetNode = self.nodes[edge.target]
self.unvisited.remove(mainNode)
if tempDistance < targetNode.minDistance:
targetNode.minDistance = tempDistance
targetNode.previousVertex = mainNode
self.unvisited.update(targetNode)
return 0
def getShortestPathTo(self, targetId):
"""Returns list of shortest parth to targetId from source. Call only after doing ComputePath"""
path = []
mainNode = self.nodes[targetId]
while True:
path.append(mainNode)
mainNode = mainNode.previousVertex
if not mainNode:
break
return list(reversed(path))
def resetDijkstra(self):
"""Resets ComputePath but leaves graph untouched"""
for vertex in self.vertexes:
vertex.minDistance = float('inf')
vertex.previousVertex = None
return 0
答案 0 :(得分:0)
def createGraph(self, vertexes, edgesToVertexes): """Connects edges to appropriate vertexes, adds vertexes to node dictionary""" self.vertexes = vertexes for vertex in self.vertexes: for edge in edgesToVertexes: if vertex.id == edge.source: vertex.edges.append(edge) edgesToVertexes.remove(edge) self.nodes[vertex.id] = vertex return 0
我相信这是错误的=&gt; edgesToVertexes.remove(边缘)
我有类似的家庭作业,并使用了一些代码,我认为这一行不正确。它在每个循环中从涡旋中移除了一条路径。