图的遍历是从某个顶点出发,对图中所有顶点仅访问一次。若给定的图是连通的,则从图的任一顶点出发沿着边可以访问到该图的所有顶点。然而,图的遍历比树的遍历复杂很多,这是因为图中的任一顶点都可能和其余顶点相邻接,故在访问了某个顶点之后,可能沿着某条回路又回到了该顶点。为了避免重复访问同一个顶点,必须记住每个顶点是否被访问过。
目录
1.深度优先搜索遍历
1. 邻接矩阵
2. 邻接表
2.广度优先搜索遍历
(1)深度优先搜索遍历类似树的先根遍历。假设给定图G初态是所有顶点均未曾访问过,在图中任选一个顶点Vi为初始出发点,则深度优先搜索可定义为,首先访问出发点Vi,从Vi的每一个未被访问过的邻接点出发,深度优先搜索图G,直至图G中所有与Vi相通的顶点都被访问过,若图中还有未被访问的顶点,选择一个未被访问的顶点作为出发点,继续深度优先搜索。
(2)图的深度优先搜索是一个递归的过程。对于一个连通的图来说,从任一个顶点出发,执行一次深度优先搜索可以遍历图中所有顶点;而对于非连通的图来说,需要进行多次深度优先搜索才可以遍历图中所有顶点。
(3)遍历过程中,为了区分顶点是否被访问过,需要设置一个访问标志数组visit[],若顶点i未被访问,则visit[i]为0,否则visit[i]为1。
int visit[N]; //定义辅助数组记录顶点的访问状态
void DFS(int i,MGraph *g){
int j;
printf("%c",g->vexs[i]);
visit[i]=1;
for(j=0;jvexnum;j++)
if((g->arcs[i][j]==1)&&(!visit[j]))
DFS(j,g);
}
void TDFS(MGraph *g){ //深度优先遍历整个图算法
int i;
for(i=0;ivexnum;i++)
if(visit[i]!=1)
DFS(i,g);
}
void DFSL(int i,ALGraph *g){
int j;
EdgeNode *p;
printf("%c",g->adjlist[i].data);
visit[i]=1;
p=g->adjlist[i].link;
while(p){
j=p->adjvex;
if((!visit[j])){
DFSL(j,g);
}
p=p->next;
}
}
void TDFSL(ALGraph *g){
int i;
for(i=0;ivexnum;i++){
if(visit[i]==0){
DFSL(i,g);
}
}
}
(1)广度优先搜索遍历类似于树的按层次遍历。设图G的初始状态是所有顶点均未访问过,在G中任选一顶点Vi为初始出发点,则广度优先搜索的基本思想是,首先访问出发点Vi,接着依次访问Vi的所有邻接点W1,W2,W3,…,Wt;然后,再依次访问与W1,W2,…,Wt邻接的所有未曾访问的顶点,直至图G中所有与Vi相通的顶点都被访问;若图中还有未被访问的顶点,选择一个未被访问的顶点作为出发点,继续广度优先搜索
(2)广度搜索过程是一种基于层次遍历的搜索过程,类似于二叉树的层次遍历,以某个顶点为出发点,访问其所有未被访问邻接点,下一步的搜索是以刚刚被访问过的顶点为出发点继续广度搜索,而上一层刚被访问的顶点可能不止一个,需要暂存这些顶点,且下次访问要保证这些顶点的先后访问次序,因此广度优先搜索需要借助队列来暂存那些刚被访问过的顶点。广度优先搜索不需要回溯,不是递归过程。
(3)广度优先遍历算法如下:
int visited[N];
void BFS(int k,MGraph *g){
int i,j;
SqQueue qlist,*q;
q=&qlist;
q->rear=0;
q->front=0;
printf("%c",g->vexs[k]);
visited[k]=1;
q->data[q->rear]=k;
q->rear=(q->rear+1)%MAX;
while(q->rear!=q->front){
i=q->data[q->front];
q->front=(q->front+1)%MAX;
for(j=0;jarcnum;j++){
if((g->arcs[i][j]==1)&&(!visited[j])){
printf("%c",g->vexs[j]);
visited[j]=1;
q->data[q->rear]=j;
q->rear=(q->rear+1)%MAX;
}
}
}
}
void TBFS(MGraph *g){
int i;
for(i=0;ivexnum;i++){
if(visited[i]!=1){
BFS(i,g);
}
}
}
(4)对于采用邻接表存储结构的图,同样可以利用广度优先搜索的原理进行算法设计。