c++ 优先队列_图的遍历广度优先

昨天聊了图的深度优先遍历,思想大概就是我沿着一条路走到黑,直到无路可走,再退回来,找其他可以走的路,直到回到起点。

那今天说的广度优先算法呢,思路会略有不同,他就不会想深度优先算法那样,沿着一条路走到黑,而是我每一个可走的路都看一下,但不深入,先放在那里。等所有的路口都看一遍,然后再深入一点,到每个路口的下一层。这样所有的路口都一样的逐级深入。

举个例子,这就好像你要在房间里面找钥匙。深度优先遍历,就是你从第一个房间开始一查到底,把第一个房间所有的抽屉柜子犄角旮旯都看一遍。都没有,再去找第二个房间。

而广度优先算法呢,则是你先到一二三房间扫一眼,先看看桌面上都有么。然后再深入一点,看看一二三房间的地上都有钥匙么。然后再深入一点,看看一二三房间的抽屉里都有么。最后再深入一点,看看一二三房间抽屉中的衣服兜里面有钥匙么。

从这个例子就可以看出来,大家都是遍历,但思路上面会有一些不一样的地方。用图像表示广度优先算法会是这样。

b4969b7d0aede7eec3f0eeb2e53359f5.png

左边是一个图,右边是从A节点开始以广度优先方式遍历的顺序。他会先遍历第一层A,然后遍历第二层B,F,然后是第三层C,I,G,E,最后是D,H。这是大家普遍逐层深入的思想。

那这样广度优先的遍历思想要用什么方法实现呢?我们可以尝试把自己导入到这个图中,假装自己就站在A点,然后要走完所有的点。在A点的时候,我们处理完A点的遍历任务,看到了两条岔路,分别是去B点和F点,于是我应该先把这两个点记在小本本上,告诉自己一会要先去这两个点。

然后我去到了B,到了B点之后发现这个点没有被遍历过,就先处理一下操作,看到了B点的另外三个岔路口,到C,I,G。那这时候我不是会去选择走哪个,而是先记下来这三个点一会再去,因为我之前记得还要先去F点。

到了F也是一样的,处理遍历任务,然后看到两个另外的岔路G和E,先记载小本本上,发现G之前已经安排了,那么就把剩下的E记下来。

就这样我会一直根据自己小本本上记录的点,按顺序一个一个的走完,直到发现小本本上再也没有要去的地方了。这样遍历就完成了。

那么这个记录的小本本,就是先进先出的队列,先记在上面的先去,后记在上面的后去。图遍历的时候,这个队列大概会是如下图这个样子。

7ff3faef5888f5f69047784514c40e1e.png

最后贴一下代码,广度优先遍历的代码如下

class EdgeNode:    def __init__(self, adjvex = None, nxt = None,weight=None):        self.adjvex = adjvex        self.weight = weight        self.nxt = nxt# 结点class VertexNode:    def __init__(self,data = None, firstedge = None):        self.data = data        self.firstedge = firstedge# 邻接表class Adgraph:    def __init__(self):        self.vertex_list = []    def build(self,vex_list,adj_matrix):        """        通过邻接矩阵构造图        :param vex_list: 节点数据        :param adj_matrix: 邻接矩阵        """        for i in vex_list:            self.vertex_list.append(VertexNode(i))        for i in range(len(vex_list)):            for j in range(len(vex_list)):                v = adj_matrix[i][j]                if v == 0:                    continue                elif v == INFINITY:                    continue                else:                    edge_node = EdgeNode(j,weight=v)                    vex_node = self.vertex_list[i]                    e = vex_node.firstedge                    if e is None:                        vex_node.firstedge = edge_node                    else:                        while e.nxt is not None:                            e = e.nxt                        e.nxt = edge_nodedef BFS(ad_graph):    # 遍历过程中使用的队列    q = queue.Queue()    # 初始化遍历标记表    visit_list = []    for i in range(len(ad_graph.vertex_list)):        visit_list.append(False)    # 遍历所有的节点    for i in range(len(ad_graph.vertex_list)):        if not visit_list[i]:            visit_list[i] = True  # 标记节点已遍历过            vetex = ad_graph.vertex_list[i]            print(vetex.data)  # 进行节点操作,可以换成其他操作            q.put(vetex)  # 将遍历过的节点加入队列            while not q.empty():  # 对栈内节点进行操作                v = q.get()  # 从栈中获取节点                e = v.firstedge  # 获取节点的边                while e is not None:                    if not visit_list[e.adjvex]:  # 判断边连接的节点是否遍历过,如果没有进一步操作                        visit_list[e.adjvex] = True  # 标记遍历                        print(ad_graph.vertex_list[e.adjvex].data)  # 打印节点,可以换成其他操作                        q.put(ad_graph.vertex_list[e.adjvex])  # 将节点放入队列                    e = e.nxt
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值