无向图的连通分量

45 篇文章 0 订阅

无向图的连通分量

一、对无向图进行遍历时

(一)对于连通图,仅需要从图中任一顶点出发,进行深度优先搜索或广度优先搜索,便可访问到图中所有顶点。

(二)对于非连通图,则需从多个顶点出发进行搜索,而每一次从一个新的起始点出发进行搜索过程中得到的顶点访问序列恰为其各个连通分量中的顶点集。

 

二、连通分量举例

         (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[20][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\n",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\n",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[20][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,20);          /*    建立邻接表      */
   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");    
   printf("\nThe end of the dfs are:\n");              /* 换行               */
  // getch();
}

参考: http://www.edushanghai.org/Item/7807.aspx

  • 1
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java代码,用于输出无向图连通分量: ```java import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; public class Graph { private ArrayList<Integer>[] adjList; public Graph(int n) { adjList = new ArrayList[n]; for (int i = 0; i < n; i++) { adjList[i] = new ArrayList<>(); } } public void addEdge(int u, int v) { adjList[u].add(v); adjList[v].add(u); } public void printConnectedComponents() { boolean[] visited = new boolean[adjList.length]; for (int i = 0; i < adjList.length; i++) { if (!visited[i]) { Queue<Integer> queue = new LinkedList<>(); queue.add(i); visited[i] = true; while (!queue.isEmpty()) { int node = queue.poll(); System.out.print(node + " "); for (int neighbor : adjList[node]) { if (!visited[neighbor]) { queue.add(neighbor); visited[neighbor] = true; } } } System.out.println(); } } } } ``` 上述代码中,我们定义了一个Graph类,该类包含一个adjList数组,用于保存节点的邻接列表。addEdge方法用于向图中添加边。printConnectedComponents方法用于输出图的连通分量。 在printConnectedComponents方法中,我们使用一个boolean类型的visited数组来记录每个节点是否已经被访问过。然后,我们遍历所有节点,如果某个节点没有被访问过,就从该节点开始进行广度优先搜索。在搜索过程中,我们将已经访问过的节点标记为visited,并将它们加入到队列中。最后,我们输出搜索到的所有节点,这些节点就是该图的一个连通分量。我们重复以上过程,直到所有节点都被访问过为止。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值