人工智能大作业——python实现BFS和DFS算法

python实现BFS和DFS算法

1 需要遍历的图

人工智能大作业——python实现BFS和DFS算法_第1张图片

2 算法设计过程

2.1 BFS程序设计

算法步骤:

1、创建一个队列,选择遍历的起点插入到队列中。
2、创建一个记录节点是否被遍历过的set,以防止节点被多次遍历形成(多次遍历亦有可能陷入死循环)。
3、当队列不为空时,从队中弹出节点并输出以记录。并依次遍历将该节点的下一层节点,依次插入到队尾。插到队尾之前需要先检查该子节点是否已被遍历,遍历过则不插入,没遍历过则插入并在visited集合中记录该点。
4、重复3直到队列为空,此时所有节点均被遍历,并且是“由内向外”。

复杂度分析:

需要注意的是复杂度的好坏取决于图的存储结构,也就是图是以邻接表存储还是以邻接矩阵存储。

  • 时间复杂度:
    邻接表存储时,从一个顶点开始搜索时,访问未被访问过的节点,最坏情况下是所有邻接点均未被访问过(即遍历所有点所有边后才找到终点),这时每个邻接点和边均要被访问一次(邻接表是一维数组存节点,链表存边(节点间关系)来实现的),所以 T = O ( V + E ) T=O(V+E) T=OV+E,其中V是顶点数,E是边数。
    邻接矩阵存储时,查找每个顶点的邻接点所需时间为 O ( V ) O(V) O(V)(邻接矩阵是由二维数组存储边,一维数组存储点来实现的),即遍历该节点所在的该行该列。又有n个顶点,故算总的时间复杂度为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2)
  • 空间复杂度:
    无论是在邻接表还是邻接矩阵中存储,都需要借助一个辅助队列,V个顶点均需入队,最坏的情况下,空间复杂度为 O ( V ) O(V) OV

2.2 DFS程序设计

算法步骤:

1、创建一个记录遍历节点的set,与BFS同理。再创建一个数组,此数组是为了模仿栈的操作。数组中包含一个个的含有两个元素的子数组,子数组中第一个元素存图的节点,第二个元素存图节点的邻接点遍历情况(0表示邻接点还未遍历,1表示已经有1个邻接点被遍历,以此类推,此元素作为临界判断的条件)。
2、若栈不为空,且节点在图中拥有邻接点,则将邻接点记录到栈中(append),并标记此邻接点已被遍历;每次记录一个邻接点时,对节点的遍历数字+1;若遍历到底了,也就是当前节点没有邻接点了,则开始从栈中弹出元素(pop)。
3、弹出到开始节点时,一条“深路径”就被遍历出来了。继续从开始节点的下一个邻接点继续向“深处”遍历。需要注意的是,从开始节点的2号邻接点遍历时,需要记录开始节点已经遍历两个邻接点了!
4、重复第3步,当开始节点没有邻接点可以遍历时,将开始节点弹出,此时栈为空,深度优先遍历结束。

复杂度分析:

  • 时间复杂度:
    邻接表表示时,查找所有顶点的邻接点所需时间为 O ( E ) O(E) O(E),访问顶点的邻接点所花时间为 O ( V ) O(V) O(V),此时,总的时间复杂度为 O ( V + E ) O(V + E) O(V+E)
    邻接矩阵表示时,查找每个顶点的邻接点所需时间为 O ( V ) O(V) O(V),要查找整个矩阵,故总的时间复杂度度为 O ( V 2 ) O(V^2) O(V2)
  • 空间复杂度:
    DFS算法时一个递归算法,需要借助递归工作栈,所以它的空间复杂度为 O ( V ) O(V) O(V)

3 程序源代码

  • BFS代码
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2022-01-02 11:17
from queue import Queue

def bfs(graph, start):
    # 创建一个set记录点是否已被遍历
    visited = set()
    q = Queue()
    q.put(start)
    while not q.empty():
        u = q.get()
        print(u)
        for v in graph.get(u, []):
            if v not in visited:
                visited.add(v)
                q.put(v)

graph = {1: [4, 2], 2: [3, 4], 3: [4], 4: [5]}
bfs(graph, 1)
  • DFS代码
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time : 2022-01-02 11:18
def dfs(graph, start):
	# 创建一个set记录点是否已被遍历
    visited = set()
    # python没有直接实现栈,这里使用list模拟栈操作
    # 入栈就是向列表中append一个元素,出栈就是pop列表中最后一个元素
    stack = [[start, 0]]
    print(start)
    while stack:
        v, next_idx = stack[-1]
        # 临界条件:图中点没有下一个邻接点或者邻接点全部遍历完毕
        if (v not in graph) or (next_idx >=len(graph[v])):
            stack.pop()
            continue
        next = graph[v][next_idx]
        # 记录当前节点的邻接点入栈数量
        stack[-1][1] += 1
        if next in visited:
            continue
        print(next)
        visited.add(next)
        stack.append([next, 0])

graph = {1: [4, 2], 2: [3, 4], 3: [4], 4: [5]}
dfs(graph, 1)

4 运行结果

人工智能大作业——python实现BFS和DFS算法_第2张图片
人工智能大作业——python实现BFS和DFS算法_第3张图片

5 参考文章

https://blog.csdn.net/qq_38830891/article/details/96564390

你可能感兴趣的:(人工智能大作业,深度优先,算法,人工智能)