数据结构之图:图的搜索,Python代码实现——23

图的搜索

深度优先搜索(Depth First Search)

定义
从例子出发理解

  • DFS是一种用于遍历或搜寻树类或图类数据结构的算法,这种算法从根结点出发(如果是图,则任意选择一个顶点作为根结点),在回溯之前会尽可能地遍历每一个分支。
  • DFS类似于树的先序遍历
    在这里插入图片描述
    假设根结点为A,左结点优先于右结点,并且不会重复遍历,
    则上图的DFS路径:A→B→D→F→E→C→G
    如果不遍历时不标记已遍历过的结点,则会重复遍历,
    DFS路径会是:A→B→D→F→E→A,循环无法结束

从即将实现的代码设计中理解

  • 指定一个索引如0对其进行DFS,
  • 在其存放相连结点的队列queue中按顺序获取子结点,第一个为6,标记6为已搜寻
  • 然后对6的子结点,按顺序搜索,第一个为0,0在最开始就提前标记已搜寻,
  • 转向第二个子结点4,标记4为已搜寻,
  • 接下来对4的子结点搜寻,以此类推直到搜寻到一个结点它的所有子结点都被搜寻过了
  • 就往回后退,后退过程中逐个检查是否存在未搜寻的结点,如果有则搜寻,否则回到最初的0结点,进行下一个子结点搜寻
    在这里插入图片描述
方法与属性设计
  1. self.G 接收传入的无向图(上一节实现的)
  2. self.marked 标记已经遍历过的顶点,True为标记,False为未标记
  3. self.count 对顶点计数,初始值为0,运行完代码它应该为顶点的数量
  4. is_marked() 返回marked的值
  5. dfs()对图进行深度优先搜索
  6. count_all_connected()返回所有相连的顶点(count)
Python代码实现
from Structure.graph.Undigraph import Undigraph


class DepthFirstSearch:
    def __init__(self, graph, x):
        """The vertex [x] is also a index of the graph G"""
        self.G = graph
        self.marked = [False for _ in range(self.G.vertex)]
        self.count = 0  # Count the vertices connected with the vertex x
        self.dfs(x)

    def is_marked(self, x):
        return self.marked[x] is True

    def dfs(self, x):
        self.marked[x] = True
        edges = self.G.get_edges_of(x)
        for n in edges:
            if not self.marked[n]:
                self.dfs(n)
        self.count += 1

    def count_all_connected(self):
        return self.count


if __name__ == '__main__':
    UG = Undigraph(13)
    UG.add_edge(0, 5)
    UG.add_edge(0, 1)
    UG.add_edge(0, 2)
    UG.add_edge(0, 6)
    UG.add_edge(5, 3)
    UG.add_edge(5, 4)
    UG.add_edge(3, 4)
    UG.add_edge(4, 6)
    UG.add_edge(7, 8)
    UG.add_edge(9, 10)
    UG.add_edge(9, 11)
    UG.add_edge(9, 12)
    UG.add_edge(11, 12)

    vertex1 = 0
    DFS = DepthFirstSearch(UG, vertex1)

    print(f"Count all the vertices connected with the vertex[{vertex1}]: {DFS.count_all_connected()}")

    vertex2 = 5
    print(f"If vertex[{vertex2}] is connected with vertex[{vertex1}]? {DFS.is_marked(vertex2)}")

    vertex3 = 7
    print(f"If vertex[{vertex3}] is connected with vertex[{vertex1}]? {DFS.is_marked(vertex3)}")
运行结果
Count all the vertices connected with the vertex[0]: 7
If vertex[5] is connected with vertex[0]? True
If vertex[7] is connected with vertex[0]? False

调用上一节实现的无向图,运行即完成了DFS
附上搜寻的图:
在这里插入图片描述

广度优先搜索(Breadth First Search)

定义
从示例来理解

  • BFS是一种用于遍历或搜寻树类或图类数据结构的算法,这种算法从根结点出发(如果是图,则任意选择一个顶点作为根结点),有时会引用“搜索键”,来对当前所有相邻结点优先于下一层结点的顺序进行遍历或搜索。
  • BFS类似树中的层次遍历
    在这里插入图片描述
    假设从V1结点出发,则遍历顺序是:V1→V2→V3→V4→V5→V6→V7→V8

从即将实现的代码设计中理解

  • 回想树的层序遍历(layer_ergodic)中,遍历时借助了一个辅助队列
  • 将根结点存入到辅助队列,然后将队列中的元素弹出来
  • 弹出来发现它有子结点,将左右子结点先后放入到辅助队列,然后继续弹出一个结点
  • 为左子结点,判断其是否还有子结点,有则放入队列
  • 同样的对右子结点进行弹出判断。。。以此类推,直到没有元素可弹为止
    在这里插入图片描述
主要方法与属性设计

DFS相同的设计属性就不重复介绍了

  1. self.queue BFS的辅助队列
  2. bfs() 对传入类中的图进行广度优先遍历
Python代码实现
from Structure.graph.Undigraph import Undigraph


class BreadthFirstSearch:
    def __init__(self, graph, x):
        self.graph = graph
        self.marked = [False for _ in range(self.graph.vertex)]
        self.count = 0
        self.queue = []
        self.bfs(x)
        # self.dfs1(x)

    def is_marked(self, x):
        return self.marked[x]

    def bfs(self, x):
        self.marked[x] = True
        self.queue += self.graph.v_edges[x]
        while self.queue:
            next_vertex = self.queue.pop(0)
            if self.is_marked(next_vertex):
                continue
            print(f"Next vertex is {next_vertex}")
            self.marked[next_vertex] = True
            if self.graph.v_edges[next_vertex]:
                self.queue += self.graph.v_edges[next_vertex]
            self.count += 1
        self.count += 1

    def count_all_connected(self):
        return self.count


if __name__ == '__main__':
    UG = Undigraph(13)
    UG.add_edge(0, 5)
    UG.add_edge(0, 1)
    UG.add_edge(0, 2)
    UG.add_edge(0, 6)
    UG.add_edge(5, 3)
    UG.add_edge(5, 4)
    UG.add_edge(3, 4)
    UG.add_edge(4, 6)
    UG.add_edge(7, 8)
    UG.add_edge(9, 10)
    UG.add_edge(9, 11)
    UG.add_edge(9, 12)
    UG.add_edge(11, 12)

    vertex1 = 0
    BFS = BreadthFirstSearch(UG, vertex1)

    print(f"Count all the vertices connected with the vertex[{vertex1}]: {BFS.count_all_connected()}")

    vertex2 = 3
    print(f"If vertex[{vertex2}] is connected with vertex[{vertex1}]? {BFS.is_marked(vertex2)}")

    vertex3 = 7
    print(f"If vertex[{vertex3}] is connected with vertex[{vertex1}]? {BFS.is_marked(vertex3)}")
运行结果
Next vertex is 5
Next vertex is 1
Next vertex is 2
Next vertex is 6
Next vertex is 3
Next vertex is 4
Count all the vertices connected with the vertex[0]: 7
If vertex[3] is connected with vertex[0]? True
If vertex[7] is connected with vertex[0]? False

搜寻结果是 (0),5,1,2,6,3,4符合广度优先遍历顺序
附上搜寻的图:
在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值