图的遍历
图的遍历就是从图的某个顶点出发,访遍图中其余结点,并且使图中的每个顶点被访问一次的过程。图的遍历方式主要有两种:深度优先搜索遍历和广度优先搜索遍历。
深度优先搜索遍历
深度优先搜索遍历是类似于树的先序遍历,尽可能的对纵深方向进行搜索。基本思想为从图的某个顶点v0出发,访问此节点,然后依次从各个未被访问的邻接点出发深度优先搜素遍历图,直至图中所有和v0有路径相通的顶点都被访问到。
遍历注意问题:
(1)图中顶点没有首尾之分,因此必须指定访问的出发顶点。
(2)在遍历过程中,必须设置顶点是否被访问的标志,保存每个顶点都只被访问一次。
(3)一个顶点可能有多个邻接点,而这些邻接点的访问次序是任意的,因此图的顶点遍历不唯一。
【递归深度优先搜索遍历连通子图】
int visited[MAXVEX]={0}; //标志数组
int FirstAdjVex(MatGraph *g,int v0)//寻找它的第一个邻接点
{
int i=v0,j;
for(j=0;j<g->vexnum;j++)
{
if(g->arcs[i][j]!=0&&visited[j]==0)//如果邻接矩阵存的值不为0并且没有被访问过
return j;
}
return -1;
}
int NextAdjVex(MatGraph *g,int v0,int w)////寻找它的下一个邻接点
{
int i=v0,j;
for(j=0;j<g->vexnum;j++)
{
if(g->arcs[i][j]!=0&&j!=w&&visited[j]==0)//如果邻接矩阵存的值不为0,不是第一个邻接点并且没有被访问过
{
return j;
}
}
return -1;
}
void DFS(MatGraph *g,int v0)//遍历
{
int w;
visit(g,v0);
visited[v0]=1;
w=FirstAdjVex(g,v0);//v0 3
//w -1
while(w!=-1)
{
if(!visited[w])
DFS(g,w);
w=NextAdjVex(g,v0,w);
}
}
void TraverseG(MatGraph *g)//深度优先
{
int v;
for(v=0;v<g->vexnum;v++)
{
visited[v]=0;
}
for(v=0;v<g->vexnum;v++)
{
if(!visited[v])
DFS(g,v);
}
}
广度优先搜索遍历
图的广度优先搜索遍历相当于树的按照层次遍历。基本思想为从图中的某个顶点v0出发,在访问此顶点之后依次访问它没有被访问的邻接点,之后按这些邻接点被访问的先后次序依次访问他们的邻接点,直至所有和v0有路径相通的顶点都被访问到。
广度优先搜索遍历可以借助队列保存已访问过的结点,使得先访问顶点的邻接点在下一轮被优先访问到,搜索过程中,每访问一个顶点就将其入队,当队头元素出队时将其未被访问的邻接点入队,每个顶点入队一次。
【广度优先搜索遍历连通子图】
void BFS(MatGraph *g,int v0)
{
Queue Q;
Q=(Queue)malloc(sizeof(queue));
int w;int v;
visit(g,v0);
visited[v0]=1;
InitQueue(Q);
EnterQueue(Q,v0);//入队
while(Empty(Q)!=0)
{
DeleteQueue(Q,&v);//出队
w=FirstAdjVex(g,v); //
while(w!=-1)
{
if(!visited[w])
{
visit(g,w);
visited[w]=1;
EnterQueue(Q,w);
}
w=NextAdjVex(g,v,w); //
}
}
}
void TraverseGB(MatGraph *g)//广度优先
{
int v;
for(v=0;v<g->vexnum;v++)
{
visited[v]=0;
}
for(v=0;v<g->vexnum;v++)
{
if(!visited[v])
BFS(g,v);
}
}