1. 广度优先搜索(BFS)
a. 基本思想:类似二叉树的层序遍历,从起始结点v访问,接着依次访问v未被访问的邻接顶点w1,w2,w3,……,wi。再从w1,w2,….., wi等开始访问,与上述相同模式。还可以应用于Dijkstra单源最短路径算法和Prim最小生成算法。
b. 代码
bool visited[MAX_VERTEX_NUM]; //访问标记数组
void BFSTraverse(Graph G){
//对图G进行广度优先遍历,设访问函数为visit()
for(i=0;i<G.vexnum;++i)
visited[i]=FALSE; //访问标记数组初始化
InitQueue(Q); //初始化辅助队列Q
for(i=0;i<G.vexnum;++i) //从0号开始遍历
if(!visited[i])
BFS(G,i); //vi未被访问过,从vi开始BFS
}
void BFS(Graph G,int v){
//从顶点v出发,广度优先遍历图G,算法借助一个辅助队列Q
visit(v); //访问初始化顶点v
visited[v]=TRUE; //对v做已访问标记
Enqueue(Q,v); //顶点v入队列
while(!isEmpty(Q)){
DeQueue(Q, v); //顶点v出队列
for(w=FristNeighbor(G,v);W>=0;w=NextNeighbor(G,v,W)) //检测v所有邻接点
if(!visited[w]){ //w为v的尚未访问的邻接顶点
visit(w);
visited[w] = TRUE; //对w做已访问标记
EnQueue(Q,w); //顶点w入队列
}//if
}//while
}
c. 示意图
d. 性能分析
无论是邻接表还是邻接矩阵的存储方式,都会使用到一个辅助队列Q。使用邻接表时,访问是以顶点表作为基准,依次访问边表,故时间复杂度O(|E|+|V|)。当采用邻接矩阵时,访问每个结点都是O(|V|),故算法是O(|V|^2).
2. 深度优先搜素(DFS)
a. 基本思想:类似树的先序遍历,重点突出这个“深”字。从访问图中某一起始顶点v, 然后从v出发,访问与v邻接且未被访问的点w, 再访问与w1邻接且未访问的w2, 按此方式不断深入。当不能再继续向下访问时,依次退回到最近被访问的顶点。
b. 代码(看其过程就看的出来,递归将是极其简便的方式)
bool visited[MAX_VERTEX_NUM]; //访问标记数组
void DFSTraverse(Graph G){
//对图G进行深度优先遍历,访问函数为visit()
for(v=0;v<G.vexnum;++v)
visited[v] = FALSE; //初始化已访问标记数据
for(v=0;v<G.vexnum;++v) //本代码中是从v=0开始遍历
if(!visited[v])
DFS(G,v);
}
void DFS(Graph G,int v){
//从顶点出发,采用递归思想,深度优先遍历图G
visit(v); //访问顶点v
visited[v] = TRUE;
for(w=FristNeighbor(G,v);w>=0;w=NextNeighor(G,v,w))
if(!visited[w]){ //w为u尚未访问的邻接顶点
DFS(G,w);
}//if
}
c. 性能分析
递归算法,借助一个递归工作栈,故空间复杂度为O(|V|)。和深度优先遍历一样,其时间复杂度与存储方式相关。使用邻接表时,使用顶点表查看,依次访问边表,故时间复杂度O(|E|+|V|)。使用邻接矩阵表示,则查找每个顶点都是O(V),故时间复杂度为O(|V|^2)。