简体   繁体   English

Python BFS没有给出最短路径

[英]Python BFS not giving the shortest path

I have implemented breadth-first search according to the pseudo-code in CLRS. 我已经根据CLRS中的伪代码实现了广度优先搜索。

However, it's not always giving me the shortest path between two nodes, as you can clearly see on the image below. 但是,这并不总是为我提供两个节点之间的最短路径,如下图所示。

在此处输入图片说明

Here it went 10 -> 5 -> 1 -> 6 -> 0 but it should clearly have gone through 10 -> 1 -> 0. 在这里它经过了10-> 5-> 1-> 6-> 0,但是显然它应该经过10-> 1-> 0。

Nodes and edges: 节点和边:

[[6, 7], [5, 0, 4], [6, 0, 4], [9, 4], [8, 2], [4, 9, 10], [1], [0], [9, 0], [7, 7], [8, 3, 1]]

Distances: 距离:

[0, 2, 4, 5, 3, 3, 1, 1, 4, 4, 4]

Colors ( 2 stands for black ): 颜色(2代表黑色):

[2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]

Predecessors: 前辈:

[None, 6, 4, 10, 1, 1, 0, 0, 4, 5, 5]

I can't figure out what's happening here as it seems that I'm doing exactly what's described in CLRS. 我无法弄清这里正在发生什么,因为我似乎完全按照CLRS中的描述进行操作。 Most of the times it gets the right path but sometimes it goes wrong for unknown reasons. 在大多数情况下,它会走正确的路,但有时由于未知原因它会出错。 There's also a possibility that I'm just drawing the graph wrong with networkx, I don't know. 不知道,还有可能是我使用networkx绘制了错误的图形。

The overall idea is that the code below generates random graphs until it finds one where it's possible to draw the shortest path between nodes a and b (ie a and b are not disjoint ). 总体思路是,下面的代码生成随机图,直到找到一个可以在节点a和b之间绘制最短路径的位置(即a和b都不相交)。

Graph() is my own class and nx.Graph() is a different function from the networkx library. Graph()是我自己的类,nx.Graph()是与networkx库不同的函数。

from collections import deque
import networkx as nx
import matplotlib.pyplot as plt
import random

class Graph(object):
    def __init__(self,graph):
        self.nodes = graph
        self.colors = [0] * len(graph)
        self.distances = [len(graph) + 1000] * len(graph)
        self.predecessor = [None] * len(graph)
        self.queue = deque()
        self.nodelist = ['red'] * len(graph)

    def BFS(self,start):
        self.__init__(self.nodes)
        self.colors[start] = 1 #GRAY
        self.distances[start] = 0
        self.queue.append(start)
        while self.queue:
            current = self.queue.popleft()
            for node in self.nodes[current]:
                if self.colors[node] == 0: #WHITE
                    self.colors[node] = 1 #GRAY
                    self.distances[node] = self.distances[current] + 1
                    self.predecessor[node] = current
                    self.queue.append(node)
            self.colors[current] = 2 #BLACK

    def draw_path(self,start,end):
        self.nodelist[start] = 'green'
        previous = end
        while previous != start:
            self.nodelist[previous] = 'green'
            previous = self.predecessor[previous]
            print(previous,self.distances[previous])
        return


while 1:
    try:
        graph = []

        for i in range(0,15):
            t = random.randint(0,3)
            if t == 0:
                graph.append([random.randint(0,10)])
            if t == 1:
                graph.append([random.randint(0,10),random.randint(0,10)])
            if t == 2:
                graph.append([random.randint(0,10),random.randint(0,10),random.randint(0,10)])
        x = Graph(graph)
        a = 0
        b = 10

        x.BFS(0)
        x.draw_path(a,b)
        print(x.nodes)
        print(x.distances)
        print(x.colors)
        print(x.predecessor)

        y = nx.Graph()
        for i in range(len(graph)):
            y.add_node(i)

        for i in range(len(graph)):
            for j in graph[i]:
                y.add_edge(i,j)

        graph_label = 'Shortest path from {0} to {1}'.format(a,b)
        nx.draw_networkx(y,with_labels=True,node_color=x.nodelist)
        plt.title(graph_label)
        plt.show()
        break
    except:
        pass

In the question, the provided graph is 在问题中,提供的图形是

[[6, 7], [5, 0, 4], [6, 0, 4], [9, 4], [8, 2], [4, 9, 10], [1], [0], [9, 0], [7, 7], [8, 3, 1]]

Which suggest that this is a directed graph, and as the start node is 0 not 10, the path is correct, as it travels backward from end to start : 这表明这是一个有图,并且当起始节点为0而不是10时,路径是正确的,因为它从末尾 开始向后移动:

10 <- 5 <- 1 <- 6 <- 0

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM