笔试算法题(50):简介 - 广度优先 & 深度优先 & 最小生成树算法
2014-05-29 10:01
351 查看
广度优先搜索&深度优先搜索(Breadth First Search & Depth First Search)
BFS优缺点:
同一层的所有节点都会加入队列,所以耗用大量空间;
仅能非递归实现;
相比DFS较快,空间换时间;
适合广度大的图;
空间复杂度:邻接矩阵O(N^2);邻接表O(N+E);
时间复杂度:O(V+E);
DFS优缺点:
无论是系统栈还是用户栈保存的节点数都只是树的深度,所以空间耗用小;
有递归和非递归实现;
由于有大量栈操作(特别是递归实现时候的系统调用),执行速度较BFS慢;
适合深度大的图;
空间复杂度:邻接矩阵O(N^2);邻接表O(N+E);
时间复杂度:O(V+E);
最小生成树算法(Minimum Spanning Tree Algorithm, eg: Kruskal, Prim)
Kruskal Algorithm
Kruskal属于贪心算法BFS策略,适用于稀疏图,使用并查集实现可具有较好性能,时间复杂度为O(ElogV),空间复杂度为O(V);
首先对于一个含有N个顶点的连通图,Kruskal首先构造一个含有N个独立顶点的图,也就是N棵只有一个顶点的树;然后从带有权值的边集合E中选择当前 权值最小的边e,如果e连接的顶点属于不同的树i和j,则使用e连接数i和j,并将e从边集合E中删除;然后从边集合E中选择下一个具有最小权值的边e, 直到左右的边都选择完毕;最终所有的N棵子树将合并成一棵树;
Prim Algorithm
时间复杂度:使用邻接矩阵实现为O(V^2);使用二叉堆和邻接表实现为O(ElogV);使用斐波那契堆实现为O(E+VlogV);Prim与 Kruskal的不同点在于,Prim从头到尾都只维护一棵树,通过从树的最远顶点相连的还未在树中的顶点中选择边权值最小的顶点进行扩展。
BFS优缺点:
同一层的所有节点都会加入队列,所以耗用大量空间;
仅能非递归实现;
相比DFS较快,空间换时间;
适合广度大的图;
空间复杂度:邻接矩阵O(N^2);邻接表O(N+E);
时间复杂度:O(V+E);
DFS优缺点:
无论是系统栈还是用户栈保存的节点数都只是树的深度,所以空间耗用小;
有递归和非递归实现;
由于有大量栈操作(特别是递归实现时候的系统调用),执行速度较BFS慢;
适合深度大的图;
空间复杂度:邻接矩阵O(N^2);邻接表O(N+E);
时间复杂度:O(V+E);
//BFS只能非递归实现,将queue替换成stack之后就是DFS procedure BFS(G,v): create a queue Q enqueue v onto Q mark v while Q is not empty: t ← Q.dequeue() if t is what we are looking for: return t for all edges e in G.incidentEdges(t) do //遍历所有与t直接相连的边e o ← G.opposite(t,e) //通过边e与t相连的顶点o if o is not marked: mark o enqueue o onto Q //DFS递归实现 procedure DFS(G,v): label v as explored for all edges e in G.incidentEdges(v) do if edge e is unexplored then w ← G.opposite(v,e) if vertex w is unexplored then label e as a discovery edge recursively call DFS(G,w) //递归调用没有访问的顶点w else label e as a back edge
最小生成树算法(Minimum Spanning Tree Algorithm, eg: Kruskal, Prim)
Kruskal Algorithm
Kruskal属于贪心算法BFS策略,适用于稀疏图,使用并查集实现可具有较好性能,时间复杂度为O(ElogV),空间复杂度为O(V);
首先对于一个含有N个顶点的连通图,Kruskal首先构造一个含有N个独立顶点的图,也就是N棵只有一个顶点的树;然后从带有权值的边集合E中选择当前 权值最小的边e,如果e连接的顶点属于不同的树i和j,则使用e连接数i和j,并将e从边集合E中删除;然后从边集合E中选择下一个具有最小权值的边e, 直到左右的边都选择完毕;最终所有的N棵子树将合并成一棵树;
Prim Algorithm
时间复杂度:使用邻接矩阵实现为O(V^2);使用二叉堆和邻接表实现为O(ElogV);使用斐波那契堆实现为O(E+VlogV);Prim与 Kruskal的不同点在于,Prim从头到尾都只维护一棵树,通过从树的最远顶点相连的还未在树中的顶点中选择边权值最小的顶点进行扩展。
MST-PRIM(G,w,r) Q←V[G] //将G的所有节点记录到Q for 每个包含于Q的u do key[u]←∞ //初始化每个节点的key,表示到根节点r的最短距离 key[r]←0 //处理根节点 p[r]←NIL while Q≠空集 do u←EXTRACT-MIN(Q) //根据节点的key值选取一个最小的节点 for 每个包含于Adj[u]的节点v do if v包含于Q and w(u,v)<key[v] then p[v]←u key[v]←w(u,v) //使用节点间的距离赋值节点v的最短距离
相关文章推荐
- 笔试算法题(10):深度优先,广度优先以及层序遍历 & 第一个仅出现一次的字符
- (百度笔试)简要说明树的深度优先、广度优先遍历算法,及非递归实现的特点
- 深度优化&广度优先 算法
- (百度笔试)简要说明树的深度优先、广度优先遍历算法,及非递归实现的特点
- (百度笔试)简要说明树的深度优先、广度优先遍历算法,及非递归实现的特点
- 图及其算法复习(Java实现) 一:存储结构,深度优先周游,广度优先周游
- 笔试算法题(46):简介 - 二叉堆 & 二项树 & 二项堆 & 斐波那契堆
- 【算法学习】图相关算法编程实现-深度优先遍历和广度优先遍历
- 迷宫问题的算法(优于递归、深度优先、广度优先)
- 百度面试题——简要说明树的深度优先、广度优先遍历算法,及非递归实现的特点
- 第五讲 树-1(广度优先遍历二叉树&深度优先遍历二叉树)
- 数据结构和算法之:图的深度优先和广度优先遍历及其Java实现
- 【算法导论】图的创建,深度优先访问,广度优先访问(递归/非递归)
- 简要说明树的深度优先、广度优先遍历算法,及非递归实现的特点
- 简要说明树的深度优先、广度优先遍历算法,及非递归实现的特点
- 排序算法 & 迷宫的深度, 广度优先
- 笔试算法题(16):二叉树深度计算 & 字符串全排列
- 图的遍历-(深度优先&广度优先)
- 【Python排序搜索基本算法】之深度优先搜索、广度优先搜索、拓扑排序、强联通&Kosaraju算法
- 树的非递归遍历(深度优先:前|中|后序遍历) & (广度优先:层次遍历)