简介:
从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历(Traversing Graph)。
深度优先遍历
深度优先遍历(Depth_First_Search),也有称为深度优先搜索,简称为DFS。
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
Boolean visited[MAX]; /* 访问标志的数组 */
/* 邻接矩阵的深度优先递归算法 */
void DFS(MGraph G, int i)
{
int j;
visited[i] = TRUE;
printf("%c ", G.vexs[i]); /* 打印顶点,也可以其他操作 */
for (j=0; j<G.numVertexes; j++)
if (G.arc[i][j]==1 && !visited[j])
DFS(G, j); /* 对未访问的邻接顶点递归调用 */
}
/* 邻接矩阵的深度遍历操作 */
void DFSTraverse(MGraph G)
{
int i;
for (i=0; i<G.numVertexes; i++)
visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */
for (i=0; i<G.numVertexes; i++)
if (!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */
DFS(G, i);
}
广度优先遍历
广度优先遍历(Breadth_First_Search),又称为广度优先搜索,简称BFS。
/* 邻接矩阵的广度遍历算法 */
void BFSTraverse(MGraph G)
{
int i, j;
Queue Q;
for (i=0; i<G.numVertexes; i++)
visited[i] = FALSE;
InitQueue(&Q); /* 初始化一辅助用的队列 */
for (i=0; i<G.numVertexes; i++) /* 对每一个顶点做循环 */
{
if (!visited[i]) /* 若是未访问过就处理 */
{
visited[i] = TRUE; /* 设置当前顶点访问过 */
printf("%c ", G.vexs[i]); /* 打印顶点,也可以其他操作 */
EnQueue(&Q, i); /* 将此顶点入队列 */
while (!QueueEmpty(Q)) /* 若当前队列不为空 */
{
DeQueue(&Q, &i); /* 将队中元素出队列,赋值给i */
for (j=0; j<G.numVertexes; j++)
{
/* 判断其他顶点若与当前顶点存在边且未访问过 */
if (G.arc[i][j]==1 && !visited[j])
{
visited[j] = TRUE; /* 将找到的此顶点标记为已访问 */
printf("%c ", G.vexs[j]); /* 打印顶点 */
EnQueue(&Q, j); /* 将找到的此顶点入队列 */
}
}
}
}
}
}
总结
- 对比图的深度优先遍历与广度优先遍历算法,会发现,它们在时间复杂度上是一样的,不同之处仅仅在于对顶点访问的顺序不同。可见两者在全图遍历上是没有优劣之分的,只是视不同的情况选择不同的算法。
- 如果图顶点和边非常多,不能在短时间内遍历完成,遍历的目的是为了寻找合适的顶点,那么选择哪种遍历就要仔细斟酌了。深度优先更适合目标比较明确,以找到目标为主要目的的情况,而广度优先更适合在不断扩大遍历范围时找到相对最优解的情况。