无向图的连通分量
一、对无向图进行遍历时
(一)对于连通图,仅需要从图中任一顶点出发,进行深度优先搜索或广度优先搜索,便可访问到图中所有顶点。
(二)对于非连通图,则需从多个顶点出发进行搜索,而每一次从一个新的起始点出发进行搜索过程中得到的顶点访问序列恰为其各个连通分量中的顶点集。
二、连通分量举例
(a) 无向图G3 (b) G3的深度优先搜索森林
图7-13
对于图7-13a中的无向图G3,采用深度优先搜索DFS[cl]方法进行遍历,当从A出发可以访问到的顶点序列依次为A、L、M、J、B、F、C。这个过程调用了DFS一次;接着从D出发遍历剩下的顶点,从D出发可以访问的顶点序列为D、E。这个过程又调用了DFS一次;最后从G出发遍历图中的其余顶点K、H、I,这是第三次调用DFS。
因此,对于无向图进行DFS遍历,每一次调用DFS后都得到此非连通图的一个连通分量,调用DFS的次数就是连通分量的个数。
- /*
- 图的深度优先遍历
- 出处:一条鱼@博客园 http://www.cnblogs.com/yanlingyin/
- 2011-12-26
- */
- #include <stdlib.h>
- #include <stdio.h>
- struct node /* 图顶点结构定义 */
- {
- int vertex; /* 顶点数据信息 */
- struct node *nextnode; /* 指下一顶点的指标 */
- };
- typedef struct node *graph; /* 图形的结构新型态 */
- struct node head[9]; /* 图形顶点数组 */
- int visited[9]; /* 遍历标记数组 */
- int id[9]; /*标记连通分量的编号*/
- int count = 0; /*连通分量编号*/
- /********************根据已有的信息建立邻接表********************/
- void creategraph(int node[12][2],int num)/*num指的是图的边数*/
- {
- graph newnode; /*指向新节点的指针定义*/
- graph ptr;
- int from; /* 边的起点 */
- int to; /* 边的终点 */
- int i;
- for ( i = 0; i < num; i++ ) /* 读取边线信息,插入邻接表*/
- {
- from = node[i][0]; /* 边线的起点 */
- to = node[i][1]; /* 边线的终点 */
- /* 建立新顶点 */
- newnode = ( graph ) malloc(sizeof(struct node));
- newnode->vertex = to; /* 建立顶点内容 */
- newnode->nextnode = NULL; /* 设定指标初值 */
- ptr = &(head[from]); /* 顶点位置 */
- while ( ptr->nextnode != NULL ) /* 遍历至链表尾 */
- ptr = ptr->nextnode; /* 下一个顶点 */
- ptr->nextnode = newnode; /* 插入节点 */
- }
- }
- /********************** 图的深度优先搜寻法********************/
- void dfs(node head[9],int current){/*非递归深度优先遍历算法*/
- node* p;
- node* stack[9];
- int top=-1,vertex;
- printf("%d\t",current);
- visited[current] = 1;
- stack[++top] = head[current].nextnode;
- id[current] = count;
- while(top > -1){
- p = stack[top];
- while(p != NULL){
- vertex = p->vertex;
- if(visited[vertex] == 0){
- printf("%d\t",vertex);
- visited[vertex] = 1;
- id[vertex] = count;
- stack[++top] = head[vertex].nextnode;
- }
- p = p->nextnode;
- }
- if(p == NULL){
- top--;
- }
- }
- }
- /**********************判断两点是否连通********************/
- bool connect(int v ,int w){ /**/
- return id[v] == id[w];
- }
- /**********************连通编号********************/
- int _id(int v){
- return id[v];
- }
- /**********************连通分量个数********************/
- int _count(){
- return count;
- }
- /****************************** 主程序******************************/
- int main()
- {
- graph ptr;
- int node[12][2] = { {1, 2}, {2, 1}, /* 边线数组 */
- {1, 3}, {3, 1},
- //{1, 4}, {4, 1},
- //{2, 5}, {5, 2},
- //{2, 6}, {6, 2},
- //{3, 7}, {7, 3},
- {4, 7}, {4, 4},
- {5, 8}, {8, 5},
- {6, 7}, {7, 6},
- {7, 8}, {8, 7} };
- int i;
- //clrscr();
- for ( i = 1; i <= 8; i++ ) /* 顶点数组初始化 */
- {
- head[i].vertex = i; /* 设定顶点值 */
- head[i].nextnode = NULL; /* 指针为空 */
- visited[i] = 0; /* 设定遍历初始标志 */
- }
- creategraph(node,12); /* 建立邻接表 */
- printf("Content of the gragh's ADlist is:\n");
- for ( i = 1; i <= 8; i++ )
- {
- printf("vertex%d ->",head[i].vertex); /* 顶点值 */
- ptr = head[i].nextnode; /* 顶点位置 */
- while ( ptr != NULL ) /* 遍历至链表尾 */
- {
- printf(" %d ",ptr->vertex); /* 印出顶点内容 */
- ptr = ptr->nextnode; /* 下一个顶点 */
- }
- printf("\n"); /* 换行 */
- }
- printf("\nThe end of the dfs are:\n");
- for(i=1;i<=8;i++){
- if(visited[i] == 0){
- dfs(head,1); /* 打印输出遍历过程 */
- count++;
- printf("\n");
- }
- }
-
- }