图的遍历:指从图的某一顶点出发,按照某种搜索方法沿着图中的边,对所有节点访问一次且仅一次。
图的遍历主要有两种算法:广度优先遍历和深度优先遍历
这两种遍历算法,我在考研期间有复习过,所以现在写到博客上(算法的实现前提是都是基于图的邻接表的存储方式存储的)
我们知道,通常图的存储方式有两种:邻接矩阵和邻接表,本篇中的存储方式则是基于邻接表的方式存储的。
存储结构:
typedef struct ArcNode{//边表结点
int adjex;//该边所指向的下一个顶点的位置
struct ArcNode *next;//指向下一条边的指针
}ArcNode;
typedef struct VNode{
int data;//存放顶点信息
ArcNode *firstarc;//指向第一个边表结点的指针
}VNode,Adjlist[50];
typedef struct{
Adjlist adjlist;//存放顶点表的数组
int vernum,arcnum;//存放的顶点数和边数
}Graph;
图的广度优先遍历
思想:
首先给定访问的初始顶点v,由该顶点v出发,依次访问与它相邻且未访问过的节点w1,w2,w3........wi,直至访问完。然后再依次访问与w1相邻且未访问过的节点,以此类推,直至所有的节点都访问过了。
实现代码:
#include<iostream>
#include<queue>
using namespace std;
bool visited[50];
//该算法是使用到了图的邻接表的存储方法实现的
typedef struct ArcNode{//边表结点
int adjex;//该边所指向的下一个顶点的位置
struct ArcNode *next;//指向下一条边的指针
}ArcNode;
typedef struct VNode{
int data;//存放顶点信息
ArcNode *firstarc;//指向第一个边表结点的指针
}VNode,Adjlist[50];
typedef struct{
Adjlist adjlist;//存放顶点表的数组
int vernum,arcnum;//存放的顶点数和边数
}Graph;
void visit(Graph G,int v){
cout<<"现在访问的节点是"<<(G.adjlist[v]).data<<endl;
}
//广度优先遍历
void BFS(Graph G,int v){
visit(G,v);//访问起始结点v
visited[v]=true;//置访问标记
queue<int> q;//声明定义队列q
q.push(v);//将已访问过的顶点v入队列
while(!q.empty()){//队列不为空时
v=q.front();//取队首元素
q.pop();//出队列
ArcNode *p=(G.adjlist[v]).firstarc;//p指向其第一个边表结点处
while(p){//p不为空时
if(!visited[p->adjex]){//该顶点未被访问过时
visit(G,p->adjex);
visited[v]=true;
q.push(p->adjex);
}
else p=p->next;//若该边已被访问过,则指向下一条
}
}
}
void BFS_Traverse(Graph G){
int i;
for(i=0;i<G.vernum;i++){
visited[i]=false;
}
for(int j=0;j<G.vernum;j++){
if(!visited[j]){
BFS(G,i);}
}
}
同时,基于广度优先遍历的实例也有很多,比如求单源最短路径(即求从一个顶点出发,到其它顶点的最短路径问题)
思想:
设置数组d[i]用于记录到每个顶点的距离,开始时将其初始化为无穷大,并设置起始顶点的d[v]=0,利用广度优先遍历算法,所有与v顶点相邻接的顶点i,d[i]=d[v]+1;以此类推,具体实现如下:
//单源最短路径
void BFS_Min(Graph G,int v){
int d[50];
for(int i=0;i<G.vernum;i++){//置数组中的每个元素的d[i](标识距离)都为无穷大
d[i]=9999;
}
visit(G,v);
visited[v]=true;
d[v]=0;//因为是计算的v到其他节点的距离,所以v到自己的距离为0
queue<int> q2;
q2.push(v);
while(!q2.empty()){
v=q2.front();
q2.pop();
ArcNode *p2=(G.adjlist[v]).firstarc;//指向第一个边表结点
if(p2){
visit(G,p2->adjex);
visited[p2->adjex]=true;
d[p2->adjex]=d[v]+1;
q2.push(p2->adjex);
}
else p2=p2->next;
}
}
深度优先遍历算法:
思想:
尽可能深的搜索,由起始顶点v出发,访问与v邻接且未被访问的任意顶点w1,再访问与w1邻接且未被访问的任意顶点w2,依次访问,直至全部都访问到。
我们采用递归的方式实现,先访问起始顶点,并置访问标记,定义指针p指向该节点的第一个边表结点
当p未被访问过时,递归调用DFS算法进行访问,当p已被访问过,则执行p=p->next,移到下一个边表结点。
实现:
//深度优先遍历
//采用递归的方法实现
void DFS(Graph G,int v){
visit(G,v);
visited[v]=true;
ArcNode *p=(G.adjlist[v]).firstarc;//定位到第一个边表结点
if(!visited[p->adjex]){//如果改变没有访问过,则递归调用dfs访问
DFS(G,p->adjex);
}
}
以上就是图的遍历的两种算法的实现