当前位置:   article > 正文

python 深度优先搜索DFS和广度优先搜索BFS_python中代码实现使用深度优先搜索和广度优先搜索分别找到从a到i的路径

python中代码实现使用深度优先搜索和广度优先搜索分别找到从a到i的路径

模板

模板来源:蓝桥杯必备模板(python蓝桥杯)-CSDN博客

  1. def dfs(参数):
  2. if (越界不合法情况):
  3. return
  4. if (终点边界,输出答案):
  5. return
  6. for (循环枚举所有方案):
  7. if(未被标记): # if (越界不合法情况): 也可以放这一块写
  8. (标记)
  9. dfs(下一层)
  10. (还原标记) #回溯
  1. """此处以迷宫问题为例,讲解视频在原作者文章中 """
  2. #M:map地图 G:go走过路径 q=deque():双向队列 q.popleft() 头节点从左边出队
  3. from collections import deque #导入数据结构deque
  4. q=deque([(0,0)]) #1.化队列,迷宫开始位置坐标(0,0)
  5. n,m=map(int,input().split())
  6. M=[[int(i) for i in input()] for j in range(n)] #模拟地图
  7. G=[['']*m for i in range(n)] #记录到从起点到该点走过路径的方向(根据题意设置)
  8. while q:
  9. x,y=q.popleft()
  10. if x==n-1 and y==m-1: #2.设置结束条件,输出答案
  11. print(len(G[-1][-1]))
  12. print(G[-1][-1])
  13. break
  14. for i,j,k in [(1,0,'D'),(0,-1,'L'),(0,1,'R'),(-1,0,'U')]:#3.下一步路,遍历可以走的四个方向,得到下一个坐标(a,b)。
  15. a,b=x+i,y+j
  16. #3.判断合理,判断坐标是否越界,是否之前遍历过。
  17. if 0<=a<n and 0<=b<m and M[a][b]==0:
  18. M[a][b]=1
  19. #4.迭代赋值:判断合理就进行标记,然后添加到队列最后,路径表上增加此刻的方向。
  20. q.append((a,b))
  21. G[a][b]=G[x][y]+k

DFS

空间复杂度是n,不具有最短路效应,因为如果数据量一旦过大,递归树会越来越大最终导致爆栈。对于DFS而言,只要有解即可适合一些思路比较奇怪,对空间要求高的题目。

  1. 基本思想: 从起始节点开始,尽可能深地访问图的节点,直到达到最深处,然后回溯到上一个节点,再继续探索未访问的分支。

  2. 实现方式: 使用递归或栈来实现。递归是一种天然的深度优先搜索方法,而使用栈也可以手动模拟递归过程。

  3. 适用场景: 适合解决一些需要完整路径的问题,比如寻找路径、拓扑排序等。

python实现图的深度优先遍历(DFS)和广度优先遍历(BFS)算法_对像素进行dfs便利-CSDN博客

实现1
  1. """
  2. 实现1 图的非递归实现
  3. """
  4. # 深度优先 Deep First Search
  5. def DFS(graph, s):
  6. stack = [] # 建立栈
  7. stack.append(s) # 初始化栈,加头节点
  8. data = [] # 存储遍历过的数字
  9. data.append(s)
  10. while stack: # 在栈不为空时
  11. n = stack.pop() # 栈尾弹出
  12. nodes = graph[n] # 找栈尾的孩子节点
  13. for i in nodes[::-1]: # 遍历节点,如果没有遍历就加入栈,做标记
  14. if i not in data:
  15. stack.append(i)
  16. data.append(i)
  17. print(n,end=' ') # 打印
'
运行

 

 实现2

 常见搜索算法(一):深度优先和广度优先搜索 - Python笔记 (notes-of-python.readthedocs.io)

 

  1. """
  2. 实现2,在图结构中的算法实现
  3. """
  4. from collections import defaultdict
  5. # 定义图结构
  6. class Graph:
  7. def __init__(self):
  8. # 使用字典保存图
  9. self.graph = defaultdict(list)
  10. def addEdge(self, u, v):
  11. # 用于给图添加边(连接)
  12. self.graph[u].append(v)
  13. def DFSTrav(self, v, visited):
  14. # 标记已经访问过的节点
  15. visited.append(v)
  16. # 访问当前节点的相邻节点
  17. for neighbour in self.graph[v]:
  18. if neighbour not in visited:
  19. self.DFSTrav(neighbour, visited)
  20. # 递归实现
  21. def DFS(self, v):
  22. # 初始化保存已访问节点的集合
  23. visited = []
  24. # 递归遍历节点
  25. self.DFSTrav(v, visited)
  26. print(visited)
  27. # 非递归实现
  28. def DFS2(self, v):
  29. # 初始化保存已访问节点的集合
  30. visited = []
  31. stack = []
  32. stack.append(v)
  33. visited.append(v)
  34. while stack:
  35. # 访问当前节点邻居节点的第一个节点,如果没有访问,标记为已访问并入栈
  36. for i in self.graph[v]:
  37. if i not in visited:
  38. visited.append(i)
  39. stack.append(i)
  40. break
  41. # 如果当前节点所有邻居节点都已访问,将当前节点弹出(出栈)
  42. v = stack[-1]
  43. if set(self.graph[v]) < set(visited):
  44. stack.pop()
  45. print(visited)
  46. # 实例
  47. if __name__ == "__main__":
  48. # 新建图
  49. graph = Graph()
  50. graph.addEdge(0, 1)
  51. graph.addEdge(0, 2)
  52. graph.addEdge(0, 3)
  53. graph.addEdge(1, 0)
  54. graph.addEdge(2, 0)
  55. graph.addEdge(3, 0)
  56. graph.addEdge(1, 4)
  57. graph.addEdge(2, 4)
  58. graph.addEdge(3, 2)
  59. graph.addEdge(4, 1)
  60. graph.addEdge(4, 2)
  61. graph.addEdge(4, 3)
  62. # DFS遍历图:指定一个起点
  63. graph.DFS(0)
  64. graph.DFS2(0)
'
运行
  1. """
  2. 二叉树的递归实现
  3. """
  4. class Solution:
  5. def DFSTrav(self, node, visited):
  6. # 标记已经访问过的节点
  7. if node.val in visited:
  8. return
  9. visited.append(node.val)
  10. # 访问当前节点的相邻节点
  11. if node.left:
  12. self.DFSTrav(node.left, visited)
  13. if node.right:
  14. self.DFSTrav(node.right, visited)
  15. def dfs(self, root: TreeNode) -> List[List[int]]:
  16. visited = []
  17. # dfs
  18. self.DFSTrav(root, visited)
  19. print(visited)
  1. """
  2. 二叉树结构的非递归实现
  3. """
  4. class Solution:
  5. def dfs2(self, node):
  6. visited = []
  7. stack = []
  8. stack.append(node)
  9. visited.append(node.val)
  10. while stack:
  11. if not node.left and not node.right:
  12. stack.pop()
  13. node = stack[-1]
  14. if node.left and node.left.val not in visited:
  15. stack.append(node.left)
  16. visited.append(node.left.val)
  17. node = node.left
  18. elif node.right and node.right.val not in visited:
  19. stack.append(node.right)
  20. visited.append(node.right.val)
  21. node = node.right
  22. else:
  23. stack.pop()
  24. print(visited)
'
运行
  1. # 实例
  2. if __name__ == "__main__":
  3. root = TreeNode('A')
  4. root.left = TreeNode('B')
  5. root.right = TreeNode('C')
  6. root.left.left = TreeNode('D')
  7. root.left.left.right = TreeNode('G')
  8. root.right.left = TreeNode('E')
  9. root.right.right = TreeNode('F')
  10. root.right.right.left = TreeNode('H')
  11. solu = Solution()
  12. solu.dfs(root)
  13. solu.dfs2(root)

 BFS

放到树的遍历中而言,就是层序遍历(levelorder)

从根节点开始向下一层一层的搜索,具有最短路的特点,适用于需要找最短路的题目

BFS是连通图的一种遍历策略,沿着树(图)的宽度遍历树(图)的节点,最短路径算法可以采用这种策略,在二叉树中体现为一层一层的搜索,也就是层序遍历。

  1. 基本思想: 从起始节点开始,逐层访问图的节点,先访问当前层的所有节点,再逐层向下遍历。

  2. 实现方式: 使用队列来实现。从起始节点开始,将其放入队列,然后依次取出队列中的节点,并将其未访问的邻居节点放入队列。

  3. 适用场景: 适合解决一些需要最短路径或层级遍历的问题,比如最短路径、最小生成树等。

实现1
  1. """
  2. 实现1,很好的模板,我背
  3. """
  4. def BFS(graph,q): #广度优先遍历,基于队列
  5. queue=[] #建立队列
  6. queue.append(q)
  7. data=[] #记录已经遍历过的点
  8. data.append(q)
  9. while queue:
  10. n=queue.pop(0) # 队列先进先出
  11. nodes=graph[n]
  12. for j in nodes:
  13. if j not in data:
  14. queue.append(j)
  15. data.append(j)
  16. print(n, end=' ')
'
运行
  1. """
  2. 实现1的两个算法的一个实例
  3. """
  4. if __name__ == '__main__':
  5. graph = {
  6. '1': ['2', '3'],
  7. '2': ['4', '5'],
  8. '3': ['6'],
  9. '4': [],
  10. '5': [],
  11. '6': []
  12. }
  13. print("DFS:")
  14. DFS(graph, '1')
  15. print('\n')
  16. print("BFS:")
  17. BFS(graph, '1')

实现2
  1. """
  2. 实现2:图结构的BFS
  3. """
  4. def BFS(self, v):
  5. # 新建一个队列
  6. queue = []
  7. # 将访问的节点入队
  8. queue.append(v)
  9. visited = []
  10. visited.append(v)
  11. while queue:
  12. # 节点出队
  13. v = queue.pop(0)
  14. # 访问当前节点的相邻节点,如果没有访问,标记为已访问并入队
  15. for i in self.graph[v]:
  16. if i not in visited:
  17. queue.append(i)
  18. visited.append(i)
  19. print(visited)
'
运行
  1. """
  2. 实现2:二叉树的BFS
  3. """
  4. def bfs(self, root: TreeNode) -> List[List[int]]:
  5. visited = []
  6. if not root:
  7. return visited
  8. queue = [root]
  9. while queue:
  10. length = len(queue)
  11. level = []
  12. for i in range(length):
  13. node = queue.pop(0)
  14. # 存储当前节点
  15. level.append(node.val)
  16. if node.left:
  17. queue.append(node.left)
  18. if node.right:
  19. queue.append(node.right)
  20. visited.append(level)
  21. print(visited)
  22. return visited

二叉树的前序、中序、后序遍历

前序、中序和后序遍历都可以看作是DFS,对下面的二叉树进行遍历:

  1. class BinaryTree:
  2. def __init__(self, val=0, left=None, right=None):
  3. self.val = val
  4. self.left = left
  5. self.right = right
  6. class BinaryTreeTraversal:
  7. def preorder(self,root, traverse_path=[]):
  8. # 前序遍历
  9. if root == None:
  10. return traverse_path
  11. traverse_path.append(root.val)
  12. self.preorder(root.left, traverse_path)
  13. self.preorder(root.right, traverse_path)
  14. return traverse_path
  15. def inorder(self,root, traverse_path=[]):
  16. # 中序遍历
  17. if root == None:
  18. return traverse_path
  19. self.inorder(root.left, traverse_path)
  20. traverse_path.append(root.val)
  21. self.inorder(root.right, traverse_path)
  22. return traverse_path
  23. def postorder(self,root, traverse_path=[]):
  24. # 后序遍历
  25. if root == None:
  26. return
  27. self.postorder(root.left, traverse_path)
  28. self.postorder(root.right, traverse_path)
  29. traverse_path.append(root.val)
  30. return traverse_path
  31. if __name__ == "__main__":
  32. root = BinaryTree('A')
  33. root.left = BinaryTree('B')
  34. root.right = BinaryTree('C')
  35. root.left.left = BinaryTree('D')
  36. root.left.left.right = BinaryTree('G')
  37. root.right.left = BinaryTree('E')
  38. root.right.right = BinaryTree('F')
  39. root.right.right.left = BinaryTree('H')
  40. Traversal = BinaryTreeTraversal()
  41. print(Traversal.preorder(root)) #['A', 'B', 'D', 'G', 'C', 'E', 'F', 'H']
  42. print(Traversal.inorder(root)) #['D', 'G', 'B', 'A', 'E', 'C', 'H', 'F']
  43. print(Traversal.postorder(root)) #['G', 'D', 'B', 'E', 'H', 'F', 'C', 'A']
'
运行

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/923602
推荐阅读
相关标签
  

闽ICP备14008679号