1. 程式人生 > >鄰接矩陣 有向圖 判斷是否有環 是否連通 DFS C實現~

鄰接矩陣 有向圖 判斷是否有環 是否連通 DFS C實現~

1 DFS 搜尋 修改

            有向圖有環需要注意 : 按照路徑方向能組成迴路才叫有環

              例如 三邊 A->B, A->C, B->C則 構成的不是環

                          A->B,B->C,C-A 組成的才是環

// 因為是有向圖兩個頂點也可以成環 
void dfs(Graph g, int i)
{
	int j;
	color[i] = gray; //灰色 表示正在訪問
	printf("%c ", g.vex[i]);
	for (j = 0; j < g.vex_num; j++) {
		if (i != j && g.edge[i][j] != INFINITY) {//兩頂點有邊相連
			if (color[j] == white) {
				dfs(g, j);//如果該節點未訪問 繼續訪問其臨近節點
			}
			else if(color[j] == gray){
				loop_num++;
				is_dag = false; //有環
			}
		}
	}
	color[i] = black;
}

void dfs_trvsal(Graph g)
{
	int i;
	for (i = 0; i < g.vex_num; i++) {
		color[i] = white;
		loop_num = 0;
	}
	link_component = 0;
	for (i = 0; i < g.vex_num; i++) {
		if (color[i] == white) {
			link_component++;
			dfs(g, i);
		}
	}
}

完整實現 :

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXVEX 100
#define INFINITY 65535
#define TRUE 1
#define FALSE 0
#define gray -1
#define white 0
#define black 1
int loop_num; //環 數量
int color[MAXVEX];  //-1 表示灰色  0表示白色 1 表示黑色
bool is_dag = true;//是否是有向無環圖
int link_component; // 連通分量 數量
typedef int EdgeType;
typedef char VertexType;

typedef struct Graph {
	VertexType vex[MAXVEX];
	EdgeType edge[MAXVEX][MAXVEX];
	int vex_num, edge_num;
}Graph;


void init_graph(Graph *g)
{
	int i, j;
	for (i = 0; i < g->vex_num; i++) {
		for (j = 0; j < g->vex_num; j++) {
			if (i == j) {
				g->edge[i][j] = 0;
			}
			else
				g->edge[i][j] = INFINITY;
		}
	}
}

char read_char()
{
	char ch;
	do {
		ch = getchar();
	} while (!isalpha(ch));
	return ch;
}

int get_pos(Graph g, char ch)
{
	int i;
	for (i = 0; i < g.vex_num; i++) {
		if (g.vex[i] == ch)
			return i;
	}
	return -1;
}

void create_graph(Graph *g)
{
	int i, k;
	//printf("請輸入頂點數與邊數:\n");
	scanf("%d%d", &g->vex_num, &g->edge_num);
	init_graph(g);// 初始化
				  //printf("請輸入頂點資訊:\n");
	for (i = 0; i < g->vex_num; i++) {
		//scanf("%c", g->vex[i]);
		g->vex[i] = read_char();
	}
	//printf("請輸入邊的資訊:\n");
	char c1, c2;
	int p1, p2,w;
	for (k = 0; k < g->edge_num; k++) {
		c1 = read_char();
		c2 = read_char();
		scanf("%d", &w);
		p1 = get_pos(*g, c1);
		p2 = get_pos(*g, c2);
		g->edge[p1][p2] = w;//有向邊的權重
	}
}

void print_graph(Graph g)
{
	int i, j;
	for (i = 0; i < g.vex_num; i++) {
		for (j = 0; j < g.vex_num; j++) {
			if (g.edge[i][j] == INFINITY)
				printf("%5c", '*');
			else {
				printf("%5d", g.edge[i][j]);
			}
		}
		printf("\n");
	}
}
// 因為是有向圖兩個頂點也可以成環 
void dfs(Graph g, int i)
{
	int j;
	color[i] = gray; //灰色 表示正在訪問
	printf("%c ", g.vex[i]);
	for (j = 0; j < g.vex_num; j++) {
		if (i != j && g.edge[i][j] != INFINITY) {//兩頂點有邊相連
			if (color[j] == white) {
				dfs(g, j);//如果該節點未訪問 繼續訪問其臨近節點
			}
			else if(color[j] == gray){
				loop_num++;
				is_dag = false; //有環
			}
		}
	}
	color[i] = black;
}

void dfs_trvsal(Graph g)
{
	int i;
	for (i = 0; i < g.vex_num; i++) {
		color[i] = white;
		loop_num = 0;
	}
	link_component = 0;
	for (i = 0; i < g.vex_num; i++) {
		if (color[i] == white) {
			link_component++;
			dfs(g, i);
		}
	}
}


int main()
{
	Graph g;
	create_graph(&g);
	//print_graph(g);
	printf("\n\nDFS:\t");
	dfs_trvsal(g);
	printf("\n\n");
	if (is_dag) {
		printf("該有向圖無環.\n");
	}
	else {
		printf("該有向圖有%d個環.\n", loop_num);
	}
	if (link_component == 1) {
		printf("該有向圖連通.");
	}
	else {
		printf("該有向圖不連通.");
	}
	getchar();
	getchar();

	return 0;
}