图的遍历
深度优先遍历(DFS)
遍历步骤
①在访问图中某一起始顶点v后,由v出发,访问它的任一邻接顶点w;
②从w1出发,访问与w1邻接但还未被访问过的顶点w2;然后再从w2出发,进行类似的访问…
③如此进行下去,直至到达所有的邻接顶点都被访问过的顶点u为止。
④接着,退到前一次刚访问过的顶点,看是否还有其它未被访问的邻接顶点。
如果有,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;
如果没有,就再退回一步进行搜索。重复上述过程,直到连通图中所有顶点都被访问过为止。
注意:在邻接表中,并非每个链表元素(表结点)都被扫描到,稀疏图时遍历速度较快。
邻接矩阵的存储
void DFS(AMGraph G,int v){//图G为邻接矩阵类型
cout<<v;
visited[v]=true;//访问第v个顶点
for(w=0;w<G.vexnum;w++)//依次检查邻接矩阵v所在的行
if((G.arcs[v][w]!=0)&&(!visited[w]))
DFS(G,w);//w是v的邻接点,w未访问,递归调用
}
用邻接矩阵来表示图,遍历图中每一个顶点都要从头扫描该顶点所在行,时间复杂度为O(n2)。
邻接表的存储
void DFS(ALGraph G, int v){//图G为邻接表类型
cout<<v;
visited[v]=true;//访问第v个顶点
p= G.vertices[v].firstarc; //p指向v的边链表的第一个边
while(p!=NULL){//边结点非空
w=p->adjvex;//表示w是v的邻接点
if(!visited[w]) DFS(G, w);//如果w未访问,则递归调用
p=p->nextarc;//p指向下一个边结点
}}
用邻接表来表示图,虽然有2e个表结点,但只需扫描e个结点即可完成遍历,加上访问n个头结点的时间,时间复杂度为O(n+e)。
广度优先遍历(BFS)
遍历步骤
①在访问了起始点v之后,依次访问v的邻接点;
②然后再依次访问这些顶点中未被访问过的邻接点;直到所有顶点都被访问过为止。
用邻接矩阵来表示图,对于每一个被访问到的顶点,都要循环检测矩阵中的整整一行( n个元素),时间复杂度为O(n2)。
用邻接表来表示图,虽然有2e个表结点,但只需扫描e个结点即可完成遍历,加上访问n个头结点的时间,时间复杂度为O(n+e)。
非连通图的遍历
连通分量
当无向图为非连通图时,从图中某一顶点出发,利用BFS算法或DFS搜索算法不可能遍历到图中的所有顶点,只能访问到该顶点所在最大连通子图(连通分量)的所有顶点。
非连通无向图的最大连通子图
如何遍历
从每个连通分量中选择初始点,分别进行遍历,才能够访问到图中的所有顶点。
生成树
该连通图的一个极小连通子图
含有n个顶点,但只有构成一棵树的*(n-1)*条边;
使用不同的遍历方法,可以得到不同的生成树;
从不同的顶点出发,也可能得到不同的生成树;