深度优先遍历是求图的强连通分量的一个有效方法。其思路大概如下:
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"); } }