深度优先搜索、广度优先搜索的实现和特性

209 阅读2分钟

遍历搜索

  • 访问每一个节点
  • 每个节点仅仅访问一次
  • 搜索的顺序
    • 深度搜索
    • 广度搜索
    • 优先级搜索 启发式搜索 适用的场景

DFS

DFS遍历顺序-二叉树

走的顺序

  • 先从根开始
  • 走最左边的
  • 走中间的
  • 走右边的

DFS遍历顺序-图

假设从S节点开始触发

走的顺序 S(岔路) A(假设先走A 走B C都是一样的 随便挑一个就行) D G(岔路) E(假设先走的E 走E 走F都一样) B S(发现S已经访问过了 返回上一个岔路G) F C S(发现已经访问过了 就继续回)

DFS代码模版-递归写法

写法1

def dfs(node):
    # 终止条件 
    if node in visited: # terminator
        # already visited 
    	return 
	
    # 当前层的处理逻辑
    visited.add(node) 
   	
    # 下探到下一层
    dfs(node.left)
    dfs(node.right)

写法2 当前层 没有走完 会继续进入下一次 同样下一层也没走完 又继续下探到 下下层去了

visited = set() 

def dfs(node, visited):
    # 终止条件
    if node in visited:
        return 
    
    # 当前层的处理逻辑
    visited.add(node) 
    # process current node here. 
    # ...
   	
    # 下探到下一层
    for next_node in node.children(): 
        # 判断条件
        if next_node not in visited:
            dfs(next_node, visited) 
                    
# 需要先传入root根节点
dfs(root_node)
            

DFS代码模版-非递归写法

手动维护一个栈 去记录已经处理过的节点 和 未处理过的节点

def DFS(self, tree): 

    if tree.root is None: 
    return [] 
    
    # visited 定义已经访问过的元素
    # stack 放入待处理的元素
    visited , stack = [], [tree.root]
    while stack: 
	node = stack.pop() 
	visited.add(node)
        
        # 处理元素
	process (node) 
        
        # 向下挖掘出它的关联节点 放到栈中 继续处理
	nodes = generate_related_nodes(node) 
	stack.push(nodes) 

    # other processing work 
    ...

BFS(广度搜索)

广度搜索 使用的是队列 每一层想象成一个水波纹 这个平面落一滴水 一直扩散出去 铺满整个平面

广度遍历顺序-二叉树

BFS代码模版-非递归写法

def BFS(graph, start, end):
    # 放入已经访问的元素 
    visited = set()
    
    # 队列中放入未访问的元素 (可以使用双端队列)
    queue = [] 
    queue.append([start]) 
    
    while queue: 
        node = queue.pop() 
	visited.add(node)
	process(node) 
        
        # 找到关联节点 扩散出他的周围节点 继续加入队列
        # 类似一个ceo 找到他下面所有的vp 然后把所有的vp塞入队列
        nodes = generate_related_nodes(node) 
	queue.push(nodes)
	# other processing work 
	...

深度搜索(DFS) 对比 广度搜索(BFS)

遍历顺序