Primera búsqueda de amplitud de figura (BFS)
Breadth First Search es uno de los algoritmos más simples para buscar gráficos.
- 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
-
Buscar desde Fool
-
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)
-
También necesita usar una cola para organizar los vértices que se han encontrado
-
Decidir el próximo vértice para explorar (el vértice superior del equipo)
-
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')
-
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'))