【图】用python实现有向图的BFS

宽度优先搜索(BFS)是一种有效的图遍历方法,类似于二叉树的层遍历,其从初始搜索节点开始,逐层的往外扩散,特别适用于寻找两个节点间的最短距离等问题。

在BFS过程中,需要引入队列结构。在探索某节点时,将相邻节点依次入列;探索完后,再将这些节点依次出列,从而实现遍历的层次化。因此,对某个节点,其存在三种状态:(1)未探索阶段;(2)作为相邻节点入列,待探索节点;(3)探索完(即将其所有的相邻节点入列)后的阶段。

不同于二叉树的单向父子关系,无向图或有向图中均可能出现两邻接节点的双向指向关系。为了防止遍历过程中的循环,我们可以采用类似于【着色】的方式为节点在上述不同阶段进行标识。当某个节点未被探索时(即上面的状态1),才会入列。

同时为了回溯的方便,还可以引入前驱节点以及距初始节点距离的相关属性和方法。

下面就是BFS的基本代码:

# 1. 创建Vertex对象
class Vertex(object):
    """
    节点对象,在基础节点对象的基础上,添加了关于着色、前驱节点以及距离的相关属性和方法
    """
    def __init__(self, key):
        self.key = key
        self.connectedTo = {}    # 存放指向的其它节点,以Vertex:连接边weight的
        self.color = "white"   # BFS中的状态标记
        self.predecessor = None     # BFS时前驱节点的标记
        self.distance = 0          # 距离起始节点的距离标记

    def addNeighbor(self, nbr, weight):
        self.connectedTo.update({nbr: weight})

    def __str__(self):
        return str(self.key) + '-->' + str([nbr.key for nbr in self.connectedTo])

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

    def getId(self):
        return self.key

    def getWeight(self, nbr):
        weight = self.connectedTo.get(nbr)
        if weight is not None:
            return weight
        else:
            raise KeyError("No such nbr exist!")

    def getColor(self):
        return self.color

    def setColor(self, color):
        self.color = color

    def setPredecessor(self, vertex):
        self.predecessor = vertex

    def getPredecessor(self):
        return self.predecessor

    def setDistance(self, dis):
        self.distance = dis

    def getDistance(self):
        return self.distance

# 2. 创建Graph对象
class Graph(object):
    """
    图对象
    """
    def __init__(self):
        self.vertexList = {}         # 字典保存节点信息,以{key: Vertex}的方式
        self.vertexNum = 0           # 统计图节点数

    def addVertex(self, key):
        self.vertexList.update({key: Vertex(key)})
        self.vertexNum += 1

    def getVertex(self, key):
        vertex = self.vertexList.get(key)
        return vertex

    def __contains__(self, key):
        return key in self.vertexList.values()

    def addEdge(self, f, t, weight=0):
        if not self.getVertex(f):
            self.addVertex(f)
        if not self.getVertex(t):
            self.addVertex(t)
        self.vertexList[f].addNeighbor(self.vertexList[t], weight=weight)

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

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

# 3. BFS搜索过程
def BFS(graph: Graph, start):
    """
    图的宽度遍历算法,采用队列不断加入新发现的节点
    """
    quene = Quene()
    startVertex = graph.getVertex(start)
    quene.enquene(startVertex)
    while not quene.isEmpty():
        currentVertex = quene.dequene()      # type: Vertex
        for v in currentVertex.getConnections():   # type: Vertex
            if v.getColor() == 'white':
                v.setColor('gray')
                v.setPredecessor(currentVertex)
                v.setDistance(currentVertex.getDistance()+1)
                quene.enquene(v)
        currentVertex.setColor('black')
    return graph



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值