深度优先遍历是求图的强连通分量的一个有效方法。其思路大概如下:
1)在有向图上,以某一顶点进行深度优先遍历,并按其所有邻接顶点都完成(退出DFL函数)顺序将顶点排列起来。即在结束函数之前,用数组存储该顶点
2)将图转置,从数组最后一顶点开始,再次进行深度优先收索。每退出函数,即是一个顶点集
#include<stdio.h>
#include<stdlib.h>
#define MAX_NUM 10
int a[MAX_NUM]; //用来存放深度优先收索结点序列(本来应该就用栈的,此处简单一点用数组来存)
int w=0;
typedef struct ArcNode //图的弧结点
{
int adjvex; //该弧所指向的顶点信息
struct ArcNode *next;
}ArcNode;
typedef struct //图的顶点结点
{
char data;
ArcNode *first; //指向第一条依附该结点的图
}VNode,AdjList[MAX_NUM];
typedef struct //图结构
{
int vexnum,arcnum; //顶点,弧的个数
AdjList vertices; //顶点结点数组
}MGraph;
void create(MGraph **g1,MGraph **g2,int n,int m); //创建图
void insert(MGraph *g, int l1,int l2); //插入弧
void DSL(MGraph *g,int visited[],int i,int sign); //深度优先遍历图
void research(MGraph *g);
void research1(MGraph *g);
void main()
{
int n,m;
MGraph *g1,*g2;
printf("输入顶点和弧的个数:\n");
scanf("%d%d",&n,&m);
create(&g1,&g2,n,m);
printf("输出深度优先搜索顺序:\n");
research(g1);
printf("\n");
printf("以行为单位输出强连通分量:\n");
research1(g2);
printf("\n");
}
//插入弧结点信息
void insert(MGraph *g,int l1,int l2)
{
ArcNode *p,*q;
p=g->vertices[l1].first;
if(!p) //当该弧尾原来是孤独结点
{
q=(ArcNode*)malloc(sizeof(ArcNode));
q->adjvex=l2;
q->next=NULL;
g->vertices[l1].first=q;
}
else
{
while(p->next)
{
p=p->next;
}
q=(ArcNode*)malloc(sizeof(ArcNode));
q->adjvex=l2;
q->next=NULL;
p->next=q;
}
}
//创建图信息
void create(MGraph **g1,MGraph **g2,int n,int m)
{
int i,l1,l2;
*g1=(MGraph *)malloc(sizeof(MGraph));
(*g1)->vexnum=n;
(*g1)->arcnum=m;
*g2=(MGraph *)malloc(sizeof(MGraph));
(*g2)->vexnum=n;
(*g2)->arcnum=m;
printf("输入各节点为:\n");
scanf(" ");
for(i=0;i<=n;i++)
{
scanf("%c",&(*g1)->vertices[i].data);
(*g1)->vertices[i].first=NULL;
(*g2)->vertices[i].data=(*g1)->vertices[i].data;
(*g2)->vertices[i].first=NULL;
}
printf("输入各弧信息:\n");
for(i=0;i<m;i++)
{
scanf("%d-%d",&l1,&l2);
insert(*g1,l1,l2); //建立图
insert(*g2,l2,l1); //建立逆向图
}
}
//深度优先遍历
void DSL(MGraph *g,int visited[],int i,int sign)
{
ArcNode *p;
int k;
visited[i]=1;
printf("%5c",g->vertices[i].data);
//if(sign)
// a[w++]=i;
for(p=g->vertices[i].first;p;p=p->next)
{
k=p->adjvex;
if(!visited[k])
DSL(g,visited,k,sign);
}
if(sign)
a[w++]=i;
}
void research(MGraph *g) //第一次深度优先搜索
{
int i;
int visited[MAX_NUM];
for(i=0;i<g->vexnum;i++)
visited[i]=0;
for(i=0;i<g->vexnum;i++)
if(!visited[i])
DSL(g,visited,i,1);
}
void research1(MGraph *g) //第二次逆向深度优先搜索
{
int i;
int visited[MAX_NUM];
for(i=0;i<g->vexnum;i++)
visited[i]=0;
for(i=--w;i>=0;i--)
if(!visited[a[i]])
{
DSL(g,visited,a[i],0);
printf("\n");
}
}