簡體   English   中英

Dijkstra算法-最短路徑中的節點順序錯誤

[英]Dijkstra's Algorithm - wrong order of nodes in shortest path

我一直在做學校作業,需要實現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
 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 

我相信這是錯誤的=> edgesToVertexes.remove(edge)

我做了類似的家庭作業,並使用了一些代碼,我認為這一行是不正確的。 它在每個循環中從渦旋中消除了一條路徑。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM