图的深度优先遍历(DFS)类似于树的先根遍历,它是树的先根遍历的推广。
图的存储结构有:数组、邻接表、十字链表、邻接多重表
1、以下程序实现用邻接表存储图,并实现图的深度优先遍历(递归)方法
#include<iostream>
using namespace std;
typedef char VertexType; //使用此方式定义顶点类型,在需要更改顶点类型时不需要在整个程序中更改,只需在此处更改即可
typedef char InfoType;
#define ERROR -1;
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点的位置编号
struct ArcNode *next; //指向下一条弧的指针
InfoType *info; //该弧相关信息的指针
}ArcNode;
typedef struct Vexnode{
VertexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}VexNode,AdjList[20];
typedef struct{
int arcnum,vexnum; //图中顶点数和弧数
AdjList vertices; //存放图中顶点的向量
}ALGraph;
bool visited[20]; //访问标志数组
int LocateVex(ALGraph G,VertexType v){ //确定顶点v在图中的位置编号
for(int i=0;i<G.vexnum;i++){
if(v==G.vertices[i].data)
return i;
}
}
int FirstAdjVex(ALGraph G,VertexType v){ //确定图中节点v的第一个邻接点的位置编号
for(int i=0;i<G.vexnum;i++){
if(v==G.vertices[i].data&&G.vertices[i].firstarc)
return G.vertices[i].firstarc->adjvex;
}
}
int NextAdjVex(ALGraph G,VertexType v,VertexType w){//确定图中从v出发,深度遍历的各个结点w
int i,j;
int flag=0;
ArcNode *p;
i=LocateVex(G,v);
j=LocateVex(G,w);
p=G.vertices[i].firstarc;
while(p){
if(p->adjvex==j){
flag=1;
break;
}
p=p->next;
}
if(flag&&p->next)
return p->next->adjvex;
else
return ERROR;
}
void CreateGraph(ALGraph &G){
VertexType v1,v2;
ArcNode *p,*q;
int i,j,k;
cout<<"请输入图的节点数和弧数:";
cin>>G.vexnum;
cin>>G.arcnum;
cout<<"图的节点数为"<<G.vexnum<<endl;
cout<<"图的弧数为:"<<G.arcnum<<endl;
cout<<"请输入图的各个节点的值:";
for(i=0;i<G.vexnum;i++){
cin>>G.vertices[i].data;
cout<<"第"<<i<<"个节点的值为:"<<G.vertices[i].data<<endl;
G.vertices[i].firstarc=NULL;
}
for(k=0;k<G.arcnum;k++){
cout<<"请输入图中连接弧的两个端点的节点值:";
cin>>v1;
cin>>v2;
i=LocateVex(G,v1);
j=LocateVex(G,v2);
cout<<"弧的两个端点v1和v2的值分别为:"<<v1<<" "<<v2<<endl;
p=(ArcNode *)malloc(sizeof(ArcNode));
q=(ArcNode *)malloc(sizeof(ArcNode));
p->next=G.vertices[i].firstarc;
q->next=G.vertices[j].firstarc;
G.vertices[i].firstarc=p;
p->adjvex=j;
G.vertices[j].firstarc=q;
q->adjvex=i;
}
}
void DFS(ALGraph G,int v){
visited[v]=true;
cout<<G.vertices[v].data<<" ";
for(int w=FirstAdjVex(G,G.vertices[v].data);w>=0;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].data)){
if(!visited[w])
DFS(G,w);
}
}
void DFSTraverse(ALGraph G){
for(int i=0;i<G.vexnum;i++)
visited[i]=false;
for(int j=0;j<G.vexnum;j++){
if(!visited[j])
DFS(G,j);
}
}
void main(){
ALGraph G;
CreateGraph(G);
cout<<"图的深度优先遍历的结果是:";
DFSTraverse(G);
cout<<endl;
}
2、以下程序实现用数组存储图,并实现图的深度优先遍历(递归)
#include<iostream> using namespace std; typedef char VertexType; typedef char InfoType; typedef int VRType; bool visited[20]; typedef struct ArcCell{ VRType adj; InfoType *info; }ArcCell,AdjMatrix[20][20]; typedef struct{ VertexType vex[20]; AdjMatrix arcs; int vexnum,arcnum; }MGraph; int LocateVex(MGraph G,VertexType v){ for(int i=0;i<G.vexnum;i++){ if(G.vex[i]==v) return i; } } void CreateGraph(MGraph &G){ int i,j,k; VertexType v1,v2; cout<<"请输入图的结点和弧的数目:"; cin>>G.vexnum; cin>>G.arcnum; for(i=0;i<G.vexnum;i++){ //此处如果使用上三角矩阵或下三角矩阵存储图,再遍历的过程中有可能会遍历不到所有的结点 for(j=0;j<G.vexnum;j++) G.arcs[i][j].adj=0; } cout<<"请输入图的各个结点的值:"; for(i=0;i<G.vexnum;i++) cin>>G.vex[i]; for(k=0;k<G.arcnum;k++){ cout<<"请输入图的连接弧的两个结点的值:"; cin>>v1; cin>>v2; i=LocateVex(G,v1); j=LocateVex(G,v2); if(G.arcs[i][j].adj==1){ //判断是否输入了重复的弧 cout<<"输入重复的弧,请重新输入:"<<endl; k--; }else{ G.arcs[i][j].adj=1; G.arcs[j][i].adj=1; } } } void DFS(MGraph G,int i){ visited[i]=true; cout<<G.vex[i]<<" "; for(int k=0;k<G.vexnum;k++){ if(G.arcs[i][k].adj==1&&visited[k]==false) DFS(G,k); } } void DFSTraverse(MGraph G){ int i; for(i=0;i<G.vexnum;i++) visited[i]=false; for(i=0;i<G.vexnum;i++){ if(visited[i]==false) DFS(G,i); } } void main(){ MGraph G; CreateGraph(G); cout<<"图的深度优先遍历的结果是:"; DFSTraverse(G); }