Figura --- Primera búsqueda de amplitud (BFS)

Primera búsqueda de amplitud de figura (BFS)

Breadth First Search es uno de los algoritmos más simples para buscar gráficos.

  1. Dado un gráfico G, y el vértice inicial s para comenzar a buscar
  • BFS busca todas las aristas que llegan al vértice desde s, yAntes de llegar a los vértices con una distancia adicional de k + 1, BFS encontrará todos los vértices con una distancia de k
  • Se puede imaginar como el proceso de construir un árbol con s como raíz, aumentando gradualmente el nivel de arriba a abajo.
  • La primera búsqueda de amplitud puede garantizar que todos los nodos hermanos se agreguen al árbol antes de aumentar el nivel

[Error en la transferencia de la imagen del enlace externo. El sitio de origen puede tener un mecanismo anti-hotlink. Se recomienda guardar la imagen y subirla directamente (img-OJuXE9FK-1614326400529) (C: \ Users \ 93623 \ AppData \ Roaming \ Typora \ typora-user-images \ image-20210219144349084.png)]

  1. Buscar desde Fool

  2. Para rastrear el proceso de adición de vértices y evitar la repetición de vértices, se agregan 3 atributos a los vértices

  • Distancia: la longitud de la ruta desde el vértice inicial hasta este vértice
  • Predecesor: se remonta al punto de partida
  • Color: identifica si este vértice aún no se ha descubierto (blanco), se ha descubierto (gris), se ha explorado o se ha explorado (negro)
  1. También necesita usar una cola para organizar los vértices que se han encontrado

  2. Decidir el próximo vértice para explorar (el vértice superior del equipo)

  3. Comenzando desde el vértice inicial s, como el vértice recién descubierto, está marcado en gris, la distancia es 0, el predecesor es Ninguno y se agrega a la cola. El siguiente es el proceso de iteración del ciclo:

  • Tome un vértice de la cabeza del equipo como vértice actual;
  • Atraviesa los vértices adyacentes del vértice actual. Si es un vértice blanco no descubierto, cambia su color a gris (descubierto), aumenta la distancia en 1 y el vértice predecesor es el vértice actual. Una vez completado el recorrido, establece el vértice a la cola. Negro, vuelve al primero del equipo en el paso 1 para tomar el vértice actual
def bfs(g, start):
    start.setDistance(0)
    start.setPred(None)
    vertQueue = Queue()
    vertQueue.enqueue(start)
    while vertQueue.size() > 0:
        currentVert = vertQueue.dequeue()
        for nbr in currentVert.getConnections():
            if nbr.getColor() == 'white':
                nbr.setColor('gray')
                nbr.setDistance(currentVert.getDistance()+1)
                vertQueue.enqueue(nbr)
        currentVert.setColor('black')
  1. El cuerpo principal del algoritmo BFS es el anidamiento de dos bucles

    El ciclo while visita cada vértice una vez, por lo que es O (∣ v ∣) \ mathbf (O) (| \ mathbf (v) |)O ( v) , y el for anidado en while, ya que cada borde se verifica una vez solo cuando su vértice u está realmente eliminado de la cola, y cada vértice se elimina de la cola como máximo una vez, por lo que el borde es como máximo Verificar 1 vez, un total deO (∣ E ∣) \ mathbf (O) (| \ mathbf (E) |)O ( E) , la complejidad del evento combinado de BFS es0 (∣ v ∣ + ∣ E ∣) 0 (| v | + | E |)0 ( v +E )

PD:

La dirección donde se almacena el archivo de escalera de palabras es: http://gis4g.pku.edu.cn/course/pythonds/#%E8%AF%BE%E7%A8%8B%E8%B5%84%E6%BA % 90 Puede copiar la URL. Abra la URL anterior en su navegador. Y busque (CTRL + F) en la página web abierta. Palabra clave: lista de palabras del alfabeto. Después de eso, puede encontrar un paquete comprimido. Descárguelo localmente y descomprímalo . Obtenga el archivo de escalera de palabras necesario para el código del artículo. Espero responder a tiempo

El siguiente código crea clases para gráficos y vértices:

# coding: utf-8

from collections.abc import *
import sys


class Vertex:
    def __init__(self, key):
        self.id = key
        self.connectedTo = {
    
    }
        # 宽度优先遍历增加以下三个属性START----
        self.color = 'white'
        self.dist = sys.maxsize
        self.pred = None
        # 宽度优先遍历增加以下三个属性END----
        # 深度优先遍历增加两个属性start------------
        self.disc = 0
        self.fin = 0
        # 深度优先遍历增加两个属性end---------------

    def addNeighbor(self, nbr, weight=0):
        self.connectedTo[nbr] = weight

    # 宽度优先增加方法start----------------
    def setColor(self, color):
        self.color = color

    def setDistance(self, d):
        self.dist = d

    def setPred(self, p):
        self.pred = p

    def getPred(self):
        return self.pred

    def getDistance(self):
        return self.dist

    def getColor(self):
        return self.color

    # 宽度优先增加方法end----------------

    # 深度优先增加方法 start---------------
    def setDiscovery(self, dtime):
        self.disc = dtime

    def setFinish(self, ftime):
        self.fin = ftime

    def getFinish(self):
        return self.fin

    def getDiscovery(self):
        return self.disc

    # 深度优先增加方法 end---------------
    # def __str__(self):
    def __repr__(self):
        return str(self.id) + 'connectedTo: ' + str([x.id for x in self.connectedTo])

    def getConnections(self):
        return self.connectedTo.keys()

    def getId(self):
        return self.id

    def getWeight(self, nbr):
        return self.connectedTo[nbr]


# v1 = Vertex("good")
# v2 = Vertex("morning")
# v1.addNeighbor(v2)
# print(v2.getConnections())
# print(v1.getWeight(v2))

class Graph:
    def __init__(self):
        # 顶点形成的集合
        self.vertList = {
    
    }
        # 顶点的数目
        self.numVertices = 0

    def addVertex(self, key):
        self.numVertices = self.numVertices + 1
        newVertex = Vertex(key)
        self.vertList[key] = newVertex
        return newVertex

    def getVertex(self, n):
        if n in self.vertList:
            return self.vertList[n]
        else:
            return None

    def __contains__(self, n):
        return n in self.vertList

    def addEdge(self, f, t, cost=0):
        if f not in self.vertList:
            nv = self.addVertex(f)
        if t not in self.vertList:
            nv = self.addVertex(t)
        self.vertList[f].addNeighbor(self.vertList[t], cost)

    def getVertices(self):
        return self.vertList.keys()

    def __iter__(self):
        return iter(self.vertList.values())


if __name__ == '__main__':
    g = Graph()
    # print(isinstance(g, Iterator))
    # print(isinstance(g, Iterable))
    for i in range(6):
        g.addVertex(i)
    print(g.vertList)
    g.addEdge(0, 1, 5)
    g.addEdge(1, 2, 4)
    g.addEdge(2, 3, 9)
    g.addEdge(3, 4, 7)

    g.addEdge(4, 0, 1)
    g.addEdge(0, 5, 2)
    g.addEdge(5, 4, 8)
    g.addEdge(3, 5, 3)
    g.addEdge(5, 2, 1)
    # 下面的for调用__iter__函数
    for v in g:
        for w in v.getConnections():
            print("(%s, %s)" % (v.getId(), w.getId()))

# print(g.vertList)

A continuación, utilice la búsqueda en amplitud del gráfico para resolver el problema de la escalera de palabras:

# coding: utf-8
# from queue import Queue
# from pythonds.graphs import Graph, Vertex
import queue_orderdlist_ccc
import graph_ccc


def traverse(y):
    x = y
    # 当前驱不为None
    print(x.getPred())
    while x.getPred() is not None:
        # 打印当前节点的id,就是这个单词
        print(x.getId())
        x = x.getPred()
    print(x.getId())


def buildGraph(wordFile):
    d = {
    
    }
    g = graph_ccc.Graph()
    wfile = open(wordFile, 'r')
    # 采用字典建立桶
    for line in wfile:
        word = line[:-1]
        # print("word++",word)
        for i in range(len(word)):
            bucket = word[:i] + '_' + word[i + 1:]
            # print("bbbb", bucket)
            if bucket in d:
                d[bucket].append(word)
            else:
                d[bucket] = [word]

    # add vertices and edges for words in the same bucket
    for bucket in d.keys():
        for word1 in d[bucket]:
            for word2 in d[bucket]:
                if word1 != word2:
                    g.addEdge(word1, word2)
    return g


def bfs(g, start):
    # print("kkkkkkkk", start)
    start.setDistance(0)
    start.setPred(None)
    # print("ddddd",start.getDistance())
    vertQueue = queue_orderdlist_ccc.Queue()
    vertQueue.enqueue(start)
    # 下面的while循环所有的顶点都放进去过一次
    while vertQueue.size() > 0:
        currentVert = vertQueue.dequeue()
        for nbr in currentVert.getConnections():
            # 说明还没有访问过
            if nbr.getColor() == 'white':
                nbr.setColor('gray')
                nbr.setDistance(currentVert.getDistance() + 1)
                nbr.setPred(currentVert)
                vertQueue.enqueue(nbr)
        currentVert.setColor('black')


if __name__ == '__main__':
    # g = buildGraph('fourletterwords.txt')
    # for item in g.vertList.values():
    #     print(item)
    wordgraph = buildGraph("fourletterwords.txt")
    bfs(wordgraph, wordgraph.getVertex('FOOL'))
    traverse(wordgraph.getVertex('SAGE'))

Supongo que te gusta

Origin blog.csdn.net/weixin_46129834/article/details/114137158
Recomendado
Clasificación