Figure --- Breadth First Search (BFS)

Figure-Breadth First Search (BFS)

Breadth First Search is one of the simplest algorithms for searching graphs.

  1. Given a graph G, and the starting vertex s to start searching
  • BFS searches all edges that reach the vertex from s, andBefore reaching the vertices with a further distance of k+1, BFS will find all vertices with a distance of k
  • It can be imagined as the process of building a tree with s as the root, gradually increasing the level from the top to the bottom
  • Breadth first search can ensure that all sibling nodes are added to the tree before increasing the level

[External link image transfer failed. The source site may have an anti-hotlinking mechanism. It is recommended to save the image and upload it directly (img-OJuXE9FK-1614326400529)(C:\Users\93623\AppData\Roaming\Typora\typora-user-images\ image-20210219144349084.png)]

  1. Search from Fool

  2. In order to track the adding process of vertices and avoid repeating vertices, 3 attributes are added to the vertices

  • Distance: The path length from the starting vertex to this vertex
  • Predecessor: can be traced back to the starting point
  • Color: Identifies whether this vertex has not been discovered (white), has been discovered (gray), or has been explored, or has been explored (black)
  1. You also need to use a queue to arrange the vertices that have been found

  2. Decide the next vertex to explore (the top vertex of the team)

  3. Starting from the starting vertex s, as the vertex just discovered, it is marked in gray, the distance is 0, the predecessor is None, and it is added to the queue. The following is the loop iteration process:

  • Take a vertex from the head of the team as the current vertex;
  • Traverse the adjacent vertices of the current vertex. If it is an undiscovered white vertex, change its color to gray (discovered), increase the distance by 1, and the predecessor vertex is the current vertex. After the traversal is completed, set the current vertex to the queue. Black, loop back to the first of the team in step 1 to take the current vertex
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. The main body of the BFS algorithm is the nesting of two loops

    The while loop visits each vertex once, so it is O (∣ v ∣) \mathbf(O)(|\mathbf(v)|)O ( v) , and the for nested in while, since each edge is checked once only when its vertex u is actually dequeued, and each vertex is dequeued at most once, so the edge is at most Check 1 time, a total ofO (∣ E ∣) \mathbf(O)(|\mathbf(E)|)O ( E) , combined BFS's event complexity is0 (∣ v ∣ + ∣ E ∣) 0(|v|+|E|)0(v+E)

PS:

The address where the word ladder file is stored is: http://gis4g.pku.edu.cn/course/pythonds/#%E8%AF%BE%E7%A8%8B%E8%B5%84%E6%BA%90 You can copy the URL. Open the above URL in your browser. And search (CTRL+F) in the opened webpage. Keyword: alphabet word list. After that, you can find a compressed package. Download it locally and unzip it. Get the word ladder file needed for the article code. Hope to reply in time

The following code creates classes for graphs and vertices:

# 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)

Next, use the breadth-first search of the graph to solve the word ladder problem:

# 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'))

Guess you like

Origin blog.csdn.net/weixin_46129834/article/details/114137158