博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
五、宽度优先搜索(BFS)
阅读量:5143 次
发布时间:2019-06-13

本文共 9325 字,大约阅读时间需要 31 分钟。

用处:

树是图的特殊状态

图的遍历 Traversal in Graph

  • 层级遍历 Level Order Traversal

   • 由点及面 Connected Component

  • 拓扑排序 Topological Sorting

最短路径 Shortest Path in Simple Graph

   • 仅限简单图求最短路径

   • 即,图中每条边长度都是1,且没有方向

 

用queue去存每一层,queue的实现LinkedList<>或ArrayDeque,不能是ArrayList会浪费时间

queue.offer() 加入队列,queue.poll()删除并取出first元素,不用add和pop异常处理不同。

DFS:模板

一、二叉树上的bfs

1、Binary Tree Level Order Traversal : 树的层级遍历  http://www.lintcode.com/problem/binary-tree-level-order-traversal/

not ac :queue.isEmpty() 写错,results 写错,level.add加节点值

Deque LinkedList<>

public class Solution {    /**     * @param root: The root of binary tree.     * @return: Level order a list of lists of integer     */    public ArrayList
> levelOrder(TreeNode root) { // write your code here ArrayList
> results = new ArrayList<>(); if (root == null) { return results; } Deque
queue = new LinkedList
(); queue.offer(root); while(!queue.isEmpty()) { ArrayList
level = new ArrayList<>(); int size = queue.size(); for (int i = 0; i < size; i++) { TreeNode head = queue.poll(); level.add(head.val); if (head.left != null) { queue.offer(head.left); } if (head.right != null) { queue.offer(head.right); } } results.add(level); } return results; }}
View Code

2、序列化: 将“内存”中结构化的数据变成“字符串”的过程 序列化:object to string 反序列化:string to object

什么时候需要序列话:

1. 将内存中的数据持久化存储时 内存中重要的数据不能只是呆在内存里,这样断电就没有了,所需需要用一种方式写入硬盘,在需要的 时候,能否再从硬盘中读出来在内存中重新创建

2. 网络传输时 机器与机器之间交换数据的时候,不可能互相去读对方的内存。只能讲数据变成字符流数据(字符串)后 通过网络传输过去。接受的一方再将字符串解析后到内存中。

常用的一些序列化手段: • XML • Json • Thrift (by Facebook) • ProtoBuf (by Google)

3、序列化算法设计考虑:

 • 压缩率。对于网络传输和磁盘存储而言,当然希望更节省。 • 如 Thrift, ProtoBuf 都是为了更快的传输数据和节省存储空间而设计的。

• 可读性。我们希望开发人员,能够通过序列化后的数据直接看懂原始数据是什么。 • 如 Json,LintCode 的输入数据

 

4、二叉树序列话

任何法进行序列化,只要保证能够解析回来即可。

LintCode 采用的是 BFS 的方式对二叉树数据进行序列化,这样的好处是,你可以更为容易的自己画出 整棵二叉树。

1) http://www.lintcode.com/en/problem/binary-tree-serialization/

class Solution {    /**     * This method will be invoked first, you should design your own algorithm      * to serialize a binary tree which denote by a root node to a string which     * can be easily deserialized by your own "deserialize" method later.     */    public String serialize(TreeNode root) {        // write your code here        if (root == null) {            return "{}";        }        ArrayList
queue = new ArrayList
(); queue.add(root); for (int i = 0; i < queue.size(); i++) { TreeNode node = queue.get(i); if (node == null) { continue; } queue.add(node.left); queue.add(node.right); } while (queue.get(queue.size() - 1) == null) { queue.remove(queue.size() - 1); } StringBuilder sb = new StringBuilder(); sb.append("{"); sb.append(queue.get(0).val); for (int i = 1; i < queue.size(); i++) { if (queue.get(i) == null) { sb.append(",#"); } else { sb.append(","); sb.append(queue.get(i).val); } } sb.append("}"); return sb.toString(); } /** * This method will be invoked second, the argument data is what exactly * you serialized at method "serialize", that means the data is not given by * system, it's given by your own serialize method. So the format of data is * designed by yourself, and deserialize it here as you serialize it in * "serialize" method. */ public TreeNode deserialize(String data) { // write your code here if (data.equals("{}")) { return null; } String[] vals = data.substring(1,data.length() - 1).split(","); ArrayList
queue = new ArrayList
(); TreeNode root = new TreeNode(Integer.parseInt(vals[0])); queue.add(root); int index = 0; boolean isLeft = true; for (int i = 1; i < vals.length; i++) { if (!vals[i].equals("#")) { TreeNode node = new TreeNode(Integer.parseInt(vals[i])); if (isLeft) { queue.get(index).left = node; } else { queue.get(index).right = node; } queue.add(node); } if (!isLeft) { index++; } isLeft = !isLeft; } return root; } }
View Code

5、图的序列化

如何表示图的邻接表:Map<Integer, Set<Integer>> 点 -- 和该点相邻的节点

如何判断图是树:1、边比点数少1

        2、判断连通性:是否有一个点没和任何点相连,从一点能访问任何一点

1)Graph Valid Tree   http://www.lintcode.com/problem/graph-valid-tree/

思路: 判断条件1

   初始化图:表示邻接表

   判断条件2

public boolean validTree(int n, int[][] edges) {        // Write your code here        //判断条件1:边和点数        if (n == 0) {            return false;        }        if (edges.length != n - 1) {            return false;        }        //初始化        Map
> graph = initializeGraph(n, edges); //判断条件2:连通性 Deque
queue = new LinkedList
(); HashSet
hash = new HashSet<>(); queue.offer(0); hash.add(0); while (!queue.isEmpty()) { int node = queue.poll(); for (Integer neighour : graph.get(node)) { if (hash.contains(neighour)) { continue; } hash.add(neighour); queue.offer(neighour); } } return hash.size() == n; } public Map
> initializeGraph(int n, int[][] edges) { Map
> graph = new HashMap<>(); for (int i = 0; i < n; i++) { graph.put(i, new HashSet
()); } for (int i = 0; i < edges.length; i++) { int u = edges[i][0]; int v = edges[i][1]; graph.get(u).add(v); graph.get(v).add(u); } return graph; }}
View Code

2)Clone Graph (F) http://www.lintcode.com/problem/clone-graph/  克隆无相图

***3步

1、得到所有的点 ArrayList<节点> nodes =   

    bfs: queue 和 hashmap

2、克隆点,old -> new映射关系

3、克隆边

记得对空检查

public class Solution {    /**     * @param node: A undirected graph node     * @return: A undirected graph node     */    public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {        // write your code here        // 1.use bfs algorithm to traverse the graph and get all nodes.        if (node == null) {            return node;        }        ArrayList
nodes = getNodes(node); //2. copy nodes, store the old->new mapping information in a hash map HashMap
map = new HashMap<>(); for (UndirectedGraphNode n : nodes) { map.put(n, new UndirectedGraphNode (n.label)); } //3.copy neighbors(edges) for (UndirectedGraphNode n : nodes) { UndirectedGraphNode newNode = map.get(n); for (UndirectedGraphNode neighbor : n.neighbors) { UndirectedGraphNode newNeighbor = map.get(neighbor); newNode.neighbors.add(newNeighbor); } } return map.get(node); } private ArrayList
getNodes(UndirectedGraphNode node) { Deque
queue = new LinkedList
(); HashSet
set = new HashSet<>(); queue.offer(node); set.add(node); while (!queue.isEmpty()) { UndirectedGraphNode head = queue.poll(); for (UndirectedGraphNode neighbor : head.neighbors) { if (!set.contains(neighbor)) { set.add(neighbor); queue.offer(neighbor); } } } return new ArrayList
(set); }}
View Code

 

 

3)Topological Sorting http://www.lintcode.com/problem/topological-sorting/ 拓扑排序

**1找根节点:没有指向它的节点---用hashmap<邻居节点,该邻接节点被指向的个数>,根节点没存在这个map里

 2.将该节点加入结果,依次从此节点开始访问

  

public class Solution {    /**     * @param graph: A list of Directed graph node     * @return: Any topological order for the given graph.     */        public ArrayList
topSort(ArrayList
graph) { // write your code here ArrayList
results = new ArrayList<>(); HashMap
map = new HashMap<>(); //用map记录 所有 被指向的节点 和 被指向的次数 for (DirectedGraphNode node : graph) { for (DirectedGraphNode neighbor: node.neighbors) { if (map.containsKey(neighbor)) { map.put(neighbor, map.get(neighbor) + 1); } else { map.put (neighbor, 1); } } } Deque
queue = new LinkedList
(); //找到未被指向的根节点,用queue记录根节点,并把该节点加入results for (DirectedGraphNode node : graph) { if (!map.containsKey(node)) { queue.offer(node); results.add(node); } } //从根节点遍历 while (!queue.isEmpty()) { DirectedGraphNode node = queue.poll(); for (DirectedGraphNode n : node.neighbors) { map.put(n,map.get(n) - 1); if (map.get(n) == 0) { results.add(n); queue.offer(n); } } } return results; }}
View Code

***矩阵和图的对比

图 Graph N个点,M条边 M最大是 O(N^2) 的级别

图上BFS时间复杂度 = O(M) 所以最坏情况可能是 O(N^2)

 

矩阵 Matrix N行M列 N*M个点,N*M*2 条边(每个点上下左右4条边,每条边被2个点共享)。

矩阵中BFS时间复杂度 = O(N * M)

 

6、矩阵中的BFS

转载于:https://www.cnblogs.com/lingli-meng/p/6557349.html

你可能感兴趣的文章
源代码如何管理
查看>>
vue怎么将一个组件引入另一个组件?
查看>>
Razor项目所感(上)
查看>>
android程序完全退出步骤
查看>>
bzoj1040: [ZJOI2008]骑士
查看>>
LeetCode 74. Search a 2D Matrix(搜索二维矩阵)
查看>>
利用SignalR来同步更新Winfrom
查看>>
反射机制
查看>>
CocoaPod
查看>>
【Finish】Python Day 9
查看>>
css3实现漂亮的按钮链接
查看>>
最大矩形面积
查看>>
[python基础] python 2与python 3的区别,一个关于对象的未知的坑
查看>>
BZOJ 1251: 序列终结者 [splay]
查看>>
Enterprise Library 加密应用程序块的设计
查看>>
深度剖析post和get的区别
查看>>
云的世界
查看>>
WPF border属性
查看>>
初识DetNet:确定性网络的前世今生
查看>>
5G边缘网络虚拟化的利器:vCPE和SD-WAN
查看>>