从图中的某一个顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这个过程就叫做图的遍历(Traversing Graph)。
图中可能存在回路,且图的任一顶点都可能与其它顶点相通,在访问完某个顶点之后可能会沿着某些边又回到了已经访问的顶点。我们要怎样避免顶点被重复访问?可以设置一个辅助数组visited[i],来标记每个被访问锅的顶点。
6.5.1 深度优先遍历
深度优先遍历(Depth_First_Search),也称深度优先搜索,简称DFS。
方法:
1、在访问图中某一起始顶点v,由v出发,访问它的任一邻接顶点w1;
2、再从w1出发,访问与w1邻接但还未被访问过的顶点w2;
3、然后再从w2出发,进行类似的访问,...
4、如此进行下去,直至到达所有的邻接顶点都被访问过的顶点u为止;
5、接着,退回一步,退到前一次刚访问过的顶点,看看是否还有其它没有被访问的邻接顶点。
6、
(1)如果,则访问此顶点,之后再从此顶点出发,进行与前述类似的访问;
(2)如果没有,就再退回一步进行搜索,重复上述过程,直到连通图中所有顶点都被访问过为止。
邻接距阵的深度遍历操作:
int visited[MAX];
//邻接距阵的深度优先递归算法
void DFS(MGraph G, int i)
{
visited[i] = 1;
printf("%c ", G.vexs[i]);
for (int j = 0; j < vexnum; j++)
if (G.arcs[i][j] == 1 && !visited[j])
DFS(G, j);
}
//邻接距阵的深度优先遍历操作
void DFSTraverse(MGraph G)
{
for (int i = 0; i < G.vexnum; i++)
visited[i] = 0; //初始化所有顶点状态都是未访问过状态
for (int i = 0; i < G.vexnum; i++)
if (!visited[i]) //对没有访问过的顶点调用DFS
DFS(G, i);
}
邻接表的深度优先遍历操作:
void DFS(GraphAdjList GL, int i)
{
ArcNode *p;
visited[i] = 1;
printf("%c ", GL.vertices[i].data);
p = GL.vertices.firstarc;
while (p)
{
if (!visited[p->adjvex])
DFS(GL, p->adjvex);
p = p->next;
}
}
void DFSTraverse(GraphAdjList GL)
{
for (int i = 0; i < GL->vexnum; i++)
visited[i] = 0;
for (int i = 0; i < GL->vexnum; i++)
if (!visited[i])
DFS(GL, i);
}
6.5.2 广度优先遍历
广度优先遍历(Breadth_First_Search),又称广度优先搜索,简称BFS。
方法:从图的某一顶点出发,依次访问该结点的所有邻接顶点,再按这些顶点被访问的先后次序依次访问与它们相邻接的所有未被访问过的顶点,重复上述过程,直至所有顶点都被访问过为止。
广度优先遍历类似与树的层序遍历。
邻接距阵的广度优先遍历算法:
//邻接距阵的广度优先遍历算法
void BFSTraverse(MGraph G)
{
Queue Q;
for (int i = 0; i < G.vexnum; i++)
visited[i] = 0;
InitQueue(&Q); //初始化辅助队列
//循环每一个顶点
for (int i = 0; i < G.vexnum; i++)
{
if (!visited[i]) //如果顶点未被访问过就访问该顶点
{
visited[i] = 1;
printf("%c ", G.vexs[i]); //访问顶点
EnQueue(&Q, i); //将顶点入队
while (!QueueEmpty(Q))
{
DeQueue(&Q, &i); //将队头元素出队
for (int j = 0; j < G.vexnum; j++)
{
//判断是否有其它顶点与当前顶点还有边未被访问
if (G.arcs[i][j] == 1 && !visited[j])
{
visited[j] = 1;
printf("%c ", G.vexs[j]);
EnQueue(&Q, j);
}
}
}
}
}
}
邻接表的广度优先遍历算法:
//邻接表的广度优先遍历算法
void BFSTraverse(ALGraph G)
{
ArcNode *p;
Queue Q;
for (int i = 0; i < G.vexnum; i++)
{
visited[i] = 0;
}
InitQueue(&Q);
for (int i = 0; i < G.vexnum; i++)
{
if (!visited[i])
{
visited[i] = 1;
printf("%c ", G.AdjList[i].data);
EnQUeue(&Q, i);
while (!QueueEmpty(Q))
{
DeQueue(&Q, &i);
p = G.AdjList[i].firstarc;//找到当前顶点的第一条边
while (p)
{
if (!visited[p->adjvex])
{
visited[p->adjvex] = 1;
printf("%c", G.AdjList[p->adjvex].data);
EnQueue(&Q, p->adjvex);
}
p = p->nextarc;
}
}
}
}
}