现在我们来思考一个问题,图如何进行遍历?
既然是遍历,我们想要得到的结果就是每条边所对应的两点都输出出来,且保证唯一性【即针对无向图无向网,根据对称性,一条边所对应的两点输出以后,对称的点不再输出】
接下来,我们介绍两种遍历图的思想,两种思想的共性就是他们都是从图中的任意点出发来依次遍历图【由于非连通图较复杂,因此我们下面只讨论连通图】
1.深度优先搜索
类似于树的先序遍历
过程:
- 从图中某个顶点v出发,访问v
- 找出刚访问过的顶点的未被访问的一个邻接点,访问该邻接点【在这里,我们规定优先访问数值较小的邻接点】。以该邻接点为新顶点,重复此步骤,直至刚访问过的顶点没有未被访问的邻接点
- 返回前一个访问过的且仍有其他未被访问的邻接点的顶点,找到该顶点的下一个未被访问的邻接点,访问该邻接点
- 重复2和3,直至所有结点都被访问过,搜索结束
代码实现:
图的DFS
void DFS(Graph &G,int v){
cout<<G.vertex[v]<<" ";//从v位置的顶点出发遍历
visited[v]=1;//将此顶点放入已访问数组中,以后不再遍历
for(int w=0;w<G.vexnum;++w){//依次访问邻接点
if(visited[v]!=1&&G.edge[v][w]!=0){//如果未被访问且两点间有边
DFS(G,w);
}
}
}
网的DFS【可输出权值】
void DFS_recur(graph &g,int v){
visited_vex_dfs[v]=1;
for(int w=0;w<g.vexnum;++w){
if((visited_vex_dfs[w]==0||visited_vex_dfs[w]==1&&visited_edge_dfs[v][w]==1)&&g.edge[v][w]!=MaxInt){//g.edge[v][w]中w为顶点v的邻接点【逐个访问】,如果不等于MaxInt说明二者之间有边相连
cout<<"("<<g.vex[v]<<" "<<g.vex[w]<<") 权值:"<<g.edge[v][w]<<endl;
visited_edge_dfs[v][w]=0;
visited_edge_dfs[w][v]=0;
DFS_recur(g,w);//visited[w]!=0表示此点未被访问
}
}
}
2.广度优先搜索
类似于树的层序遍历
过程:
- 从图中顶点v出发,访问顶点v
- 然后依次访问v的各个未被访问过的邻接点【仍然是按从小到大】
- 接下来从这些邻接点出发依次访问他们的邻接点,重复此步骤,直至顶点都被访问
代码实现:
图的BFS
void BFS(Graph &G,int v){
cout<<G.vertex[v]<<" ";//从v位置的顶点出发遍历
visited[v]=1;//将此顶点放入已访问数组中,以后不再遍历
Initqueue(Q);//初始化队列
Enqueue(Q,G.vertex[v]);//将此点入队,以便接下来使用
while(!IsEmpty(Q)){
v=Dequeue();//出队,代表接下来对出队的顶点v的邻接点进行遍历
for(int w=0;w<G.vexnum;++w){
if(visited[w]!=0&&G.edge[v][w]!=0){
cout<<G.vertex[w]<<endl;
visited[w]=1;
Enqueue(Q,G.vertex[w]);//入队
}
}
}
}
网的BFS
void BFS(graph &g,int v){
queueCreate();
visited_vex_bfs[v]=1;
Enqueue(v);
while(!isEmpty()){
v=Dequeue();
for(int w=0;w<g.vexnum;++w){
if(g.edge[v][w]!=MaxInt&&(visited_vex_bfs[w]==0||visited_vex_bfs[w]==1&&visited_edge_bfs[v][w]==1)){
cout<<"("<<g.vex[v]<<" "<<g.vex[w]<<") 权值:"<<g.edge[v][w]<<endl;
visited_vex_bfs[w]=1;
visited_edge_bfs[v][w]=0;
visited_edge_bfs[w][v]=0;
Enqueue(w);
}
}
}
}