You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于邻接表的无向加权图最短路径:非优先队列实现的顺序问题

问题:无向加权图最短路径输出顺序不符,是否需要改用优先队列?

我基于邻接表实现了无向加权图的最短路径函数,没用到优先队列,目标是计算并展示起始节点的最短路径。现在能算出从节点A出发的最短路径,但节点输出顺序和预期不符,想问下是否应该改用优先队列实现?

预期输出

B(4) C(12) D(19) E(21) F(11) G(9) H(8) I(14) J(inf)

实际输出

B(4) H(8) C(12) G(9) I(14) D(19) F(11) E(21)

邻接表

  • A- {'B': 4, 'H': 8}
  • B- {'A': 4, 'C': 8, 'H': 11}
  • C- {'B': 8, 'D': 7, 'F': 4, 'I': 2}
  • D- {'C': 7, 'E': 9, 'F': 14}
  • E- {'D': 9, 'F': 10}
  • F- {'C': 4, 'D': 14, 'E': 10, 'G': 2}
  • G- {'F': 2, 'H': 1, 'I': 6}
  • H- {'A': 8, 'B': 11, 'G': 1, 'I': 7}
  • I- {'C': 2, 'G': 6, 'H': 7}
  • J- {}

实现代码

class WGraph:
    def __init__(self, size=10):
        self.size = 10
        self.nodeList = {}
        self.adjacencyMatrix = [[0] * size for i in range(size)]  # initialize matrix

    def addNode(self, name):
        """Adds node to adjacency list"""
        self.nodeList[name] = {}

    def addEdge(self, startIndex, endIndex, weight):
        """Add edges for adjacency list and matrix"""
        self.nodeList[startIndex][endIndex] = weight
        self.nodeList[endIndex][startIndex] = weight

        index1 = list(self.nodeList.keys()).index(startIndex)
        index2 = list(self.nodeList.keys()).index(endIndex)
        self.adjacencyMatrix[index1][index2] = weight

    def displayAdjacency(self):
        """Displays adjacency list with edges and weight"""
        for node in self.nodeList:
            print(node + "- " + str(self.nodeList[node]))


    def minCostPaths(self, vertex):
        visited = {vertex: 0}
        queue = [(vertex, 0)]
        while queue:
            node, cost = queue.pop(0)
            for neighbor in self.nodeList[node]:
                if neighbor not in visited or cost + self.nodeList[node][neighbor] < visited[neighbor]:
                    visited[neighbor] = cost + self.nodeList[node][neighbor]
                    queue.append((neighbor, cost + self.nodeList[node][neighbor]))
        output = ""
        for node in visited:
            if node != vertex:
                output += f"{node}({visited[node]}) "
        return output[:-2] + ")"


# Driver Code
graph = WGraph()

graph.addNode('A')
graph.addNode('B')
graph.addNode('C')
graph.addNode('D')
graph.addNode('E')
graph.addNode('F')
graph.addNode('G')
graph.addNode('H')
graph.addNode('I')
graph.addNode('J')

graph.addEdge('A', 'B', 4)
graph.addEdge('A', 'H', 8)
graph.addEdge('B', 'C', 8)
graph.addEdge('B', 'H', 11)
graph.addEdge('C', 'D', 7)
graph.addEdge('C', 'F', 4)
graph.addEdge('C', 'I', 2)
graph.addEdge('D', 'E', 9)
graph.addEdge('D', 'F', 14)
graph.addEdge('E', 'F', 10)
graph.addEdge('F', 'G', 2)
graph.addEdge('G', 'H', 1)
graph.addEdge('G', 'I', 6)
graph.addEdge('H', 'I', 7)

graph.displayAdjacency()

print("The minimum cost paths starting at A ")
print(" Expected B(4) C(12) D(19) E(21) F(11) G(9) H(8) I(14) J(inf) ")
print(" Actually " + graph.minCostPaths('A'), end="\n")

解答

1. 输出顺序问题的本质

你当前的输出顺序是节点被首次访问的顺序,而预期输出是节点名称的字典序(B、C、D、E、F、G、H、I、J),这和是否使用优先队列无关。优先队列的作用是优化最短路径算法的时间复杂度(从类Bellman-Ford的O(V+E),优化为Dijkstra的O(E log V)),但不会直接改变最终输出的节点排序。

2. 如何修正输出顺序

要得到预期的输出顺序,只需在生成结果时,按照节点名称的字典序遍历所有节点即可,同时还要处理未被访问到的J节点(需手动标记为inf)。

修改minCostPaths函数的输出部分:

def minCostPaths(self, vertex):
    visited = {vertex: 0}
    queue = [(vertex, 0)]
    while queue:
        node, cost = queue.pop(0)
        for neighbor in self.nodeList[node]:
            if neighbor not in visited or cost + self.nodeList[node][neighbor] < visited[neighbor]:
                visited[neighbor] = cost + self.nodeList[node][neighbor]
                queue.append((neighbor, cost + self.nodeList[node][neighbor]))
    # 按节点名称字典序排序,遍历所有节点
    all_nodes = sorted(self.nodeList.keys())
    output = ""
    for node in all_nodes:
        if node != vertex:
            cost = visited.get(node, float('inf'))
            # 处理inf的显示格式
            cost_str = str(cost) if cost != float('inf') else "inf"
            output += f"{node}({cost_str}) "
    # 去掉末尾多余的空格
    return output.strip()

3. 是否需要改用优先队列?

  • 如果你的图规模较小(比如当前的10个节点),当前的实现完全够用,不需要改优先队列。
  • 如果图的节点和边数量很大,优先队列实现的Dijkstra算法会有明显的性能优势,此时建议替换。

另外,当前代码的队列处理逻辑存在重复入队的问题(同一个节点可能被多次加入队列),虽然不影响结果正确性,但会降低效率。如果要优化,不管用不用优先队列,都可以考虑标记节点是否已经达到最优状态,避免重复操作。


内容的提问来源于stack exchange,提问作者Sage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 18:25:18