若用邻接矩阵表示图,得到的DFS序列是唯一的。若用邻接表表示则不唯一。
深度优先搜索
深度优先搜索(DFS),不断探究与回溯
在探查的每一步算法都有一个当前顶点,最初的当前顶点为指定的起始顶点,对当前顶点v进行访问之后,设置访问过的顶点设置访问标志为visit[v]=true
在深度优先搜索过程中所有访问过的顶点和经过的边构成了连通的无环图,称为原图的深度优先生成树(DFS树),其包含n-1条边
访问当前顶点的所有可读入的未访问过邻接结点的while循环为主要花费时间处。
(1)若用邻接矩阵表示图
则查找每一个顶点的所有边所需时间为O(n),遍历图中所有顶点的时间为O(n2)
(2)若用邻接表表示图
沿着link链可以依次取出顶点v的所有邻接顶点。设图中有n个顶点e条边,由于总共有2e个边结点,所以扫描边的时间为O(e),每个顶点只被访问一次,故遍历图的时间复杂度为O(n+e)
//深度优先搜索(DFS)的递归算法,从位置loc开始 template <class T,class E> void DFS(Graph<T,E>& G,const T& v){ int i,loc,n=G.NumberOfVerticles(); bool *visited=new bool[n]; //辅助数组 for(i=0;i<n;i++) visited[i]=false; loc=G.getVertexPos(v); //NodeTable[loc].data==v DFS(G,loc,visited); delete []visited; } template <class T,class E> void DFS(Graph<T,E>& G,int v,bool visited[]){ //子过程 count<<G.getValue(v)<<''; visited[v]=true; int w=G.getFirstNeighbour(v); while(w!=-1){ if(!visited[w]) DFS(G,w,visited); //如果w没有访问过,递归访问顶点w w=G.getNextNeighbour(v,w); } }
无向图为非连通图时,每个极大连通子图的所有顶点构成一个连通分量。
可以使用深度优先搜索输出所有连通分量。每一棵DFS生成树都是一个极小连通子图。
所有连通分量的生成树,组成了非连通图的生成森林。
算法中调用DFS过程的次数与非连通图中的连通分量有关。而DFS过程的计算时间又和图的存储表示有关。
template <class T,class E>
void Components(Graph<T,E>& G){
int i,n=G.NumberOfVerticles();
bool *visited=new bool[n];
for(i=0;i<n;i++) visited[i]=false;
for(i=0;i<n;i++)
if(visited[i]==false){ //如果这个连通分量已经访问过,visited[i]=true
DFS(G,i,visited);
OutputNewCompoent(); //输出这个连通分量
}
}