《图论基础算法》
图论基础算法
第1部分:图的遍历
一、图的遍历
1、深度优先遍历的递归定义
从图中某顶点v出发:
1)访问顶点v;
2)依次从v的未被访问的邻接点出发,继续对图进行深度优先遍历;
3)重复上述过程,直到图中所有顶点均已被访问为止。
例:在下图中,从V0开始进行一次深度遍历的过程如图所示:
2、广度优先遍历算法的描述
从图中某未访问过的顶点v i出发:
1)访问顶点v i;
2)访问v i的所有未被访问的邻接点w1 ,w2 , …w k;
3)依次从这些邻接点出发,访问它们的所有未被访问的邻接点; 依此类推,直到图中所有访问过的顶点的邻接点都被访问;
例如:求图G 的以V0起点的广度优先序列。
由于没有规定访问邻接点的顺序,深度优先遍历和广度优先遍历的遍历序列不是唯一的。
二、图的遍历算法实现
1、深度优先遍历
根据深度优先遍历的定义,通常使用递归过程实现图的深度优先遍历。
(1)邻接矩阵:
(2)邻接表
(3)非连通图的遍历(邻接表)
2、广度优先遍历算法
(1)邻接矩阵
(2)邻接表
图的数据结构如下:
【广度优先遍历代码】
3、复杂度分析
算法的时间复杂度与图的存储方式直接相关,采取邻接矩阵方式存储时,两种算法的时间复杂度均为O(n*n);若采用邻接表存储,则算法的时间复杂度为O(n+e)。
深度优先遍历需要用到系统栈,若顶点特别多时,可以使用人工栈,以防栈溢出;广度(也称宽度)优先遍历,是一种按层遍历的方法,需要使用队列,额外空间为O(n)。
第2部分:图的最小生成树之PRIM算法
一、普里姆算法的基本思想
从连通网络G = { V, E }中的某一顶点u0出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。
以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把它的顶点加入到集合U中。如此继续下去,直到网络中的所有顶点都加入到生成树顶点集合U中为止。
二、Prim算法的基本步骤
(1)初始化:U={u0},TREE={};
(2)如果U=V(G),则输出最小生成树T,并结束算法;
(3)在所有两栖边中找一条权最小的边(u,v)(若候选两栖边中的最小边不止一条,可任选其中的一条),将边(u,v)加入到边集TREE中,并将顶点v并入集合U中。
(4)由于新顶点的加入,U的状态发生变化,需要对U与V-U之间的两栖边进行调整。
(5)转步骤(2)
Prim算法实例
对图(a)从A点进行Prim算法的过程如下:
三、Prim算法实现
1、连通图用邻接矩阵表示:
W ij当(v i,v j) E(G)且权为W ij
g[i,j]= 0 当i=j
∞否则
2、生成树的边类型:
3、算法实现的过程代码
假设从第1个顶点开始生成最小生成树。
4、Prim算法分析
1、普里姆算法的时间复杂度为O(n2),适用于稠密图。
2、优化:在选择权值最小的可行边时可以使用堆(后面在树的内容中讲解)。算法的时间复杂度为O(nlogn)
3、堆优化的Prim算法适用于稀疏图,而不优化的Prim算法适用于稠密图。