BFS模板

模板,记住这5个:
(1)针对树的BFS
1.1 无需分层遍历
    from collections import deque
	
    def levelOrderTree(root):
        if not root:
            return 
             
        q = deque([root])
        while q:
            head = q.popleft()
			do something with this head node...
            if head.left:                
                q.append(head.left)
			if head.right:
                q.append(head.right)                
        return xxx
1.2 需要分层遍历
    def levelOrderTree(root):
        if not root:
            return
                 
        q = [root]
        while q:
            new_q = []
            for node in q: # 和上面代码相比 差异就在这里 和 deque
                do something with this layer nodes...
                if node.left:
                    new_q.append(node.left)
                if node.right:
                    new_q.append(node.right)            
            q = new_q
        return xxx
		
(2)针对图的BFS
2.1 无需分层遍历
  from collections import deque
  
  def bfs_graph(root):	
    if not root: 
	    return
	
	queue = deque([root])
	seen = set([root])  
	while queue:
		head = queue.popleft()
		do something with this head...
		for neighbor in head.neighbors:
			if neighbor not in seen: # 和tree的区别无非就是多了一个是否访问过的判断
				seen.add(neighbor)
				queue.append(neighbor)
  return xxx

上述代码中:
neighbor 表示从某个点 head 出发,可以走到的下一层的节点。
set/seen 存储已经访问过的节点(已经丢到 queue 里去过的节点)
queue 存储等待被拓展到下一层的节点
set/seen 与 queue 是一对好基友,无时无刻都一起出现,往 queue 里新增一个节点,就要同时丢到 set 里。
需要分层遍历的宽度搜先搜索

2.2 需分层遍历

    def bfs_graph(root):
        if not root:
            return []
                 
        q = [root]
		seen = set([root])
        while q:
            new_q = []
            for node in q:
                do something with this layer nodes...				
				for neighbor in node.neighbors:
				    if neighbor not in seen: # 和tree的区别无非就是多了一个是否访问过的判断
					    seen.add(neighbor)
						new_q.append(neighbor)           
            q = new_q
        return xxx


(3)拓扑排序

记住下面的代码
class Solution:
    """
    @param graph: A list of Directed graph node
    @return: Any topological order for the given graph.
    """
    def topSort(self, graph):
        node_to_indegree = self.get_indegree(graph)
 
        # bfs
        order = []
        start_nodes = [n for n in graph if node_to_indegree[n] == 0]
        queue = collections.deque(start_nodes)
        while queue:
            node = queue.popleft()
            order.append(node)
            for neighbor in node.neighbors:
                node_to_indegree[neighbor] -= 1
                if node_to_indegree[neighbor] == 0:
                    queue.append(neighbor)
                 
        return order
     
    def get_indegree(self, graph):
        node_to_indegree = {x: 0 for x in graph}
 
        for node in graph:
            for neighbor in node.neighbors:
                node_to_indegree[neighbor] += 1
                 
        return node_to_indegree

算法流程
拓扑排序的算法是典型的宽度优先搜索算法,其大致流程如下:
统计所有点的入度,并初始化拓扑序列为空。
将所有入度为 0 的点,也就是那些没有任何依赖的点,放到宽度优先搜索的队列中
将队列中的点一个一个的释放出来,放到拓扑序列中,每次释放出某个点 A 的时候,就访问 A 的相邻点(所有A指向的点),并把这些点的入度减去 1。
如果发现某个点的入度被减去 1 之后变成了 0,则放入队列中。
直到队列为空时,算法结束		


一些实际案例:
https://www.cnblogs.com/bonelee/p/11724346.html

 

BFS宽度优先搜索
模板:
https://www.cnblogs.com/bonelee/p/11724346.html
BFS模板:
    def levelOrder(self, root):
        # write your code here
        if not root:
            return []
             
        q = [root]
        result = []
        while q:
            children = []
            q2 = []
            for node in q:
                children.append(node.val)
                if node.left:
                    q2.append(node.left)
                if node.right:   
                    q2.append(node.right)
            result.append(children)
            q = q2
        return result
		
BFS 递归实现		
q= [root]		
result = []

def levelOrder(q):
  if not q:
     return
  q2 = []
  for node in q:
     xxxx
	 if node.left: q2.append(node.left)
	 if node.right: q2.append(node.right)
  levelOrder(q2)
	 

		
1. BFS VS DFS
https://www.geeksforgeeks.org/difference-between-bfs-and-dfs/

2. 什么时候使用BFS
图的遍历 Traversal in Graph
• 层级遍历 Level Order Traversal
• 由点及面 Connected Component
• 拓扑排序 Topological Sorting
最短路径 Shortest Path in Simple Graph
• 仅限简单图求最短路径
• 即,图中每条边长度都是1,或者边长都相等
非递归的方式找所有方案 Iteration solution for all possible results
• 这一点我们将在后面 DFS 的课上提到

3. 题型与算法的对应关系
最短路径
简单图 → BFS
复杂图 → Dijkstra, SPFA, Floyd(一般面试不考这个)
最长路径
图可以分层 → Dynamic Programming
分层:比如走到第i一定会经过第 i-1 层(棋盘格子图是典型的例子)
不可以分层 → DFS

4.主要内容
• 二叉树上的 BFS
• 图上的 BFS
• 矩阵上的 BFS
• 拓扑排序 Topological Sorting


5. 二叉树上的 BFS
5.1 二叉树层级遍历
5.1.1 非递归实现方法讲解
https://blog.csdn.net/sinat_20177327/article/details/78285495
5.1.2 题目和非递归python实现
https://blog.csdn.net/yurenguowang/article/details/76906620
5.1.3 DFS递归方法和java实现
https://blog.csdn.net/crazy1235/article/details/51507485

5.2 二叉树的序列化
5.2.1 什么是序列化(P11)
将“内存”中结构化的数据变成“字符串”的过程
序列化:object to string
反序列化:string to object
5.2.2 什么时候需要序列化(P12)
1. 将内存中的数据持久化存储时
内存中重要的数据不能只是呆在内存里,这样断电就没有了,所需需要用一种方式写入硬盘,在需要的
时候,能否再从硬盘中读出来在内存中重新创建
2. 网络传输时
机器与机器之间交换数据的时候,不可能互相去读对方的内存。只能讲数据变成字符流数据(字符串)后
通过网络传输过去。接受的一方再将字符串解析后到内存中。
5.2.3 序列化算法(P13)
一些序列化的例子:
• 比如一个数组,里面都是整数,我们可以简单的序列化为”[1,2,3]”
• 一个整数链表,我们可以序列化为,”1->2->3”
• 一个哈希表(HashMap),我们可以序列化为,”{\”key\”: \”value\”}”
序列化算法设计时需要考虑的因素:
• 压缩率。对于网络传输和磁盘存储而言,当然希望更节省。
• 如 Thrift, ProtoBuf 都是为了更快的传输数据和节省存储空间而设计的。
• 可读性。我们希望开发人员,能够通过序列化后的数据直接看懂原始数据是什么。
• 如 Json,LintCode 的输入数据
5.2.4 使用BFS序列化
题目
https://www.lintcode.com/problem/serialize-and-deserialize-binary-tree/description
python BFS解答
https://www.jiuzhang.com/solutions/binary-tree-serialization/#tag-highlight-lang-python

5.3 二叉树上的BFS相关题目
5.3.1 Binary Tree Level Order Traversal II
题目:
http://www.lintcode.com/en/problem/binary-tree-level-order-traversal-ii/
解答:
https://blog.csdn.net/coder_orz/article/details/51583729
http://www.jiuzhang.com/solutions/binary-tree-level-order-traversal-ii/
5.3.2 Binary Tree Zigzag Order Traversal
http://www.lintcode.com/en/problem/binary-tree-zigzag-level-order-traversal/
http://www.jiuzhang.com/solutions/binary-tree-zigzag-level-order-traversal/
5.3.3 Convert Binary Tree to Linked Lists by Depth
http://www.lintcode.com/en/problem/convert-binary-tree-to-linked-lists-by-depth/
http://www.jiuzhang.com/solutions/convert-binary-tree-to-linked-lists-by-depth/

leetcode
lintcode(大部分提供解答)

  

上一篇:python学习笔记第13章:web开发之sanic框架


下一篇:机器学习笔记(十)---- KNN(K Nearst Neighbor)