《算法导论》笔记(12) 基本的图算法,最小生成树
2015-02-15 22:18
357 查看
首先是图的表示。G=(V, E),两种标准表示方法。一是邻接链表,一是邻接矩阵。邻接链表有|V|条链表,链表Adj[u]包含所有与结点u有边关联的结点v。邻接矩阵是|V|*|V|的二维矩阵,aij可用来表示结点i与j之间有无边或边的权重。
广度优先搜素。从源结点出发向外扩展,访问当前结点的全部相连结点并一一入队列,然后将队列中最前结点出列以相同方法访问其子结点,直到所有结点都被访问。访问过程中作两种标记来控制路线,已访问全部子结点的结点标为visited,已访问自身但未访问完其全部子结点的结点标为visiting。s到v的最短距离为v.d,v.d=u.d+1。树边,前驱子图,广度优先树。
深度优先搜索。探索最近发现的结点的边,若无未访问结点,则回溯其前驱结点继续搜索。直到所有结点都访问完全。访问过程中作两种标记来控制路线,已访问全部子结点的结点标为visited,已访问自身但未访问完其全部子结点的结点标为visiting。time来标记结点第一次访问的时间u.d与最后完成全部子结点访问的时间u.f。括号化定理,白色路径定理。树边,后向边,前向边,横向边。深度优先森林。
拓扑排序。有向无环图的所有结点排成线性序列,任意边的起点排在终点之前。方法是在深度优先搜索时,每当结点完成visited则加入一个链表。
强连通分量。集合内任意两个点,路径(u, v)与(v, u)同时存在,则称为一个强连通分量。寻找强连通分量的算法是运行两次深度优先搜索,第二次是转置图G(V, E' )即所有边方向逆转后的深度优先搜索,并且按照第一次搜索后各结点f值最大值开始搜索。两次搜索完成后形成的深度优先森林是各最大连通分量。证明算法的正确性:假设有结点u与连通分量C,若u.f>C.f,只有两种可能:1,图(V, E)中有路径u->C,此时若在转置图(V, E' )中有路径从u->C则证明u、C在同一连通分量中,u、C可以合并;2,图(V,
E)中u、C互相隔离,则转置图G(V, E' )中,u、C也不相连,u不会加入C所在的连通分量。
最小生成树。已有最小生成树的子集,然后用贪心法选择一条边加入子集。最终所有点加入后,得到最小生成树。 Kruskal算法,选择加入子集的原则是每次一条最短的边加入森林,直到所有点构成一棵最小生成树。Prim算法,每次在子集之外与子集连接的边中选择一条最短的边加入。
广度优先搜素。从源结点出发向外扩展,访问当前结点的全部相连结点并一一入队列,然后将队列中最前结点出列以相同方法访问其子结点,直到所有结点都被访问。访问过程中作两种标记来控制路线,已访问全部子结点的结点标为visited,已访问自身但未访问完其全部子结点的结点标为visiting。s到v的最短距离为v.d,v.d=u.d+1。树边,前驱子图,广度优先树。
BFS(G, s){ u=s; mark u as visited; u.d=0; queue.push(u); while(u){ for each v in G.Adj[u]{ if(v not visited && v not visiting) {v.d= u.d + 1; v.p=u; queue.push(v); mark v as visiting; } } mark u as visited; u=queue.pop(); } }
深度优先搜索。探索最近发现的结点的边,若无未访问结点,则回溯其前驱结点继续搜索。直到所有结点都访问完全。访问过程中作两种标记来控制路线,已访问全部子结点的结点标为visited,已访问自身但未访问完其全部子结点的结点标为visiting。time来标记结点第一次访问的时间u.d与最后完成全部子结点访问的时间u.f。括号化定理,白色路径定理。树边,后向边,前向边,横向边。深度优先森林。
DFS(G){ for each u in G{ if(u not visited && u has no prev_node) visit(u); } } visit(u){ time++; //注意,time作为全局变量,如果多线程同时搜索不同分支的子树,则有同步的问题 mark u as visiting; u.d=time; for each v in G.Adj[u]{ if(v not visited && v not visiting) {v.p=u; visit(v); } } time++; mark u as visited; u.f=time; }
拓扑排序。有向无环图的所有结点排成线性序列,任意边的起点排在终点之前。方法是在深度优先搜索时,每当结点完成visited则加入一个链表。
强连通分量。集合内任意两个点,路径(u, v)与(v, u)同时存在,则称为一个强连通分量。寻找强连通分量的算法是运行两次深度优先搜索,第二次是转置图G(V, E' )即所有边方向逆转后的深度优先搜索,并且按照第一次搜索后各结点f值最大值开始搜索。两次搜索完成后形成的深度优先森林是各最大连通分量。证明算法的正确性:假设有结点u与连通分量C,若u.f>C.f,只有两种可能:1,图(V, E)中有路径u->C,此时若在转置图(V, E' )中有路径从u->C则证明u、C在同一连通分量中,u、C可以合并;2,图(V,
E)中u、C互相隔离,则转置图G(V, E' )中,u、C也不相连,u不会加入C所在的连通分量。
最小生成树。已有最小生成树的子集,然后用贪心法选择一条边加入子集。最终所有点加入后,得到最小生成树。 Kruskal算法,选择加入子集的原则是每次一条最短的边加入森林,直到所有点构成一棵最小生成树。Prim算法,每次在子集之外与子集连接的边中选择一条最短的边加入。
MST_Kruskal(G){ E[]= sorted G.E; for each edge(u,v) in E[] { if(v not in u.Set){ add edge(u,v) to A; union(u.Set, v.Set) in one Set; } } } MST_Prim(G){ add all vertex in Q; edge(u,v) = minimum(G.E); u.key=edge; while(Q not empty){ u=Q.extract_min; mark u as MST; for each v in G.Adj[v]{ if(v not MST && v.key>w(u,v) ) {v.key=w(u,v); v.p=u; update v in Q;} } } }
相关文章推荐
- 算法导论学习笔记(17)——最小生成树
- OpenCV 2 学习笔记(12): 算法的基本设计模式<3>:单例模式(Singleton pattern)
- 图的基本算法(最小生成树)
- 图的基本算法(最小生成树)
- 《算法导论》第23章 最小生成树 个人笔记
- 无向图基本算法 -- 遍历及最小生成树算法
- 算法导论笔记:23最小生成树
- 最小生成树笔记--《算法导论》
- 图基本算法 最小生成树 Prim算法(邻接表/邻接矩阵+优先队列STL)
- 数据结构编程笔记二十:第七章 图 最小生成树算法的实现
- 最小生成树基本算法---算法导论读书笔记
- 《算法导论》笔记(15) 最小生成树 部分习题
- 《算法导论》笔记 第23章 23.1 最小生成树的形成
- 图基本算法:深度广度遍历最小生成树
- 无向图基本算法 -- 遍历及最小生成树算法
- 【算法导论笔记】最小生成树
- 最小生成树,最短路径的基本算法
- 《算法导论》笔记(14) 基本的图算法 部分习题
- 最小生成树的两种最基本的算法
- 算法笔记_164:算法提高 最小方差生成树(Java)