算法导论代码 第22章 图的基本算法

22章 图的基本算法

22.1 图的表示

22.1.1 邻接表表示法

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct graph_type *graph;
struct edge {
	int u;
	int v;
};
struct graph_node {
	int key;
	struct graph_node *next;
};
void graph_node_ini(struct graph_node *x, int key)
{
	x->key = key;
	x->next = NULL;
}

struct vertex {
	char str_vertex[256];	//顶点的字符串表示,显示用
};
void vertex_ini(struct vertex *v)
{
	strcpy(v->str_vertex, "");
}

struct graph_type {
	struct graph_node **adj;
	struct vertex *vertex_array;
	int v_num;
	int e_num;
};
//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用
graph graph_create(int v_num, char *str_vertex[])
{
	graph g = malloc(sizeof(struct graph_type));
	g->v_num = v_num;
	g->e_num = 0;
	g->adj = malloc(sizeof(struct graph_node *) * v_num);
	g->vertex_array = malloc(sizeof(struct vertex) * v_num);
	for (int i = 0; i < v_num; i++) {
		g->adj[i] = NULL;
		strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);
	}
	return g;
}

void graph_destroy(graph g)
{
	for (int i = 0; i < g->v_num; i++) {
		for (struct graph_node * x = g->adj[i]; x != NULL;) {
			struct graph_node *del=x;
			x=x->next;
			free(del);
		}
	}
	free(g->adj);
	free(g->vertex_array);
	free(g);
}

void graph_insert_edge(graph g, struct edge edge)
{
	struct graph_node *u = malloc(sizeof(struct graph_node));
	graph_node_ini(u, edge.u);
	struct graph_node *v = malloc(sizeof(struct graph_node));
	graph_node_ini(v, edge.v);
	//从表头插入,将v插入到表头u
	v->next = g->adj[edge.u];
	g->adj[edge.u] = v;
	//从表头插入,将u插入到表头v
	u->next = g->adj[edge.v];
	g->adj[edge.v] = u;
	++g->e_num;
}

void graph_display(graph g)
{
	printf("%d vertices,%d edges\n", g->v_num, g->e_num);
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: ", g->vertex_array[i].str_vertex);
		for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {
			printf("%s ", g->vertex_array[x->key].str_vertex);
		}
		printf("\n");
	}
}

int main()
{
	//数据根据书上的图22-1
	char *str_vertex[5] = { "1", "2", "3", "4", "5" };
	graph g = graph_create(5, str_vertex);
	struct edge edges[] =
	    { {0, 1}, {0, 4}, {1, 2}, {1, 3}, {1, 4}, {2, 3}, {3, 4} };
	for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {
		graph_insert_edge(g, edges[i]);
	}
	graph_display(g);
	graph_destroy(g);
	return 0;
}

21.1.2 邻接矩阵表示法

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct graph_type *graph;
struct edge {
	int u;
	int v;
};
struct vertex {
	char str_vertex[256];	//顶点的字符串表示,显示用
};
void vertex_ini(struct vertex *v)
{
	strcpy(v->str_vertex, "");
}

struct graph_type {
	int **adj;
	struct vertex *vertex_array;
	int v_num;
	int e_num;
};
//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用
graph graph_create(int v_num, char *str_vertex[])
{
	graph g = malloc(sizeof(struct graph_type));
	g->v_num = v_num;
	g->e_num = 0;
	g->adj = malloc(sizeof(int *) * v_num);
	    for (int i = 0; i < v_num; i++) {
		g->adj[i] = malloc(sizeof(int) * v_num);
		    for (int j = 0; j < v_num; j++) {
			g->adj[i][j] = 0;
		}
	}
	g->vertex_array = malloc(sizeof(struct vertex) * v_num);
	for (int i = 0; i < v_num; i++) {
		strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);
	}
	return g;
}

void graph_destroy(graph g)
{
	for (int i = 0; i < g->v_num; i++) {
		free(g->adj[i]);
	}
	free(g->adj);
	free(g->vertex_array);
	free(g);
}

void graph_insert_edge(graph g, struct edge edge)
{
	g->adj[edge.u][edge.v] = 1;
	g->adj[edge.v][edge.u] = 1;
	++g->e_num;
}

void graph_display(graph g)
{
	printf("%d vertices,%d edges\n", g->v_num, g->e_num);
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: ", g->vertex_array[i].str_vertex);
		for (int j = 0; j < g->v_num; j++) {
			if (g->adj[i][j] != 0) {
				printf("%s ", g->vertex_array[j].str_vertex);
			}
		}
		printf("\n");
	}
}

int main()
{
	//数据根据书上的图22-1
	char *str_vertex[5] = { "1", "2", "3", "4", "5" };
	graph g = graph_create(5, str_vertex);
	struct edge edges[] =
	    { {0, 1}, {0, 4}, {1, 2}, {1, 3}, {1, 4}, {2, 3}, {3, 4} };
	for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {
		graph_insert_edge(g, edges[i]);
	}
	graph_display(g);
	graph_destroy(g);
	return 0;
}

22.2 广度优先搜索

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct queue_type *queue;
struct queue_node {
	void *key;
	struct queue_node *next;
};

struct queue_type {
	struct queue_node *head;
	struct queue_node *tail;
};

void queue_node_ini(struct queue_node *node, void *key)
{
	node->key = key;
	node->next = NULL;
}

queue queue_create()
{
	queue q = malloc(sizeof(struct queue_type));
	q->head = NULL;
	q->tail = NULL;
	return q;
}

bool queue_is_empty(queue q)
{
	return q->head == NULL;
}

void queue_en_queue(queue q, void *x)
{
	struct queue_node *p = malloc(sizeof(struct queue_node));
	queue_node_ini(p, x);
	if (q->head == NULL) {
		q->head = p;
		q->tail = p;
	} else {
		q->tail->next = p;
		q->tail = p;
	}
}

void *queue_de_queue(queue q)
{
	void *key = q->head->key;
	struct queue_node *p = q->head;
	q->head = q->head->next;
	free(p);
	return key;
}

void queue_destroy(queue q, void (*free_key) (void *))
{
	while (!queue_is_empty(q)) {
		void *p = queue_de_queue(q);
		free_key(p);
	}
	free(q);
}

enum color_enum {
	color_white,
	color_gray,
	color_black
};
typedef struct graph_type *graph;
struct edge {
	int u;
	int v;
};
struct graph_node {
	int key;
	struct graph_node *next;
};
void graph_node_ini(struct graph_node *x, int key)
{
	x->key = key;
	x->next = NULL;
}

struct vertex {
	enum color_enum color;
	int dis;
	int parent;
	char str_vertex[256];	//顶点的字符串表示,显示用
};
void vertex_ini(struct vertex *v)
{
	v->color = color_white;
	v->dis = 0;
	v->parent = -1;		//顶点编号是从0开始,-1表示一个不存在的结点
	strcpy(v->str_vertex, "");
}

struct graph_type {
	struct graph_node **adj;
	struct vertex *vertex_array;
	int v_num;
	int e_num;
};
//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用
graph graph_create(int v_num, char *str_vertex[])
{
	graph g = malloc(sizeof(struct graph_type));
	g->v_num = v_num;
	g->e_num = 0;
	g->adj = malloc(sizeof(struct graph_node *) * v_num);
	g->vertex_array = malloc(sizeof(struct vertex) * v_num);
	for (int i = 0; i < v_num; i++) {
		g->adj[i] = NULL;
		strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);
	}
	return g;
}

void graph_destroy(graph g)
{
	for (int i = 0; i < g->v_num; i++) {
		for (struct graph_node * x = g->adj[i]; x != NULL;) {
			struct graph_node *del=x;
			x=x->next;
			free(del);
		}
	}
	free(g->adj);
	free(g->vertex_array);
	free(g);
}

void graph_insert_edge(graph g, struct edge edge)
{
	struct graph_node *u = malloc(sizeof(struct graph_node));
	graph_node_ini(u, edge.u);
	struct graph_node *v = malloc(sizeof(struct graph_node));
	graph_node_ini(v, edge.v);
	//从表头插入,将v插入到表头u
	v->next = g->adj[edge.u];
	g->adj[edge.u] = v;
	//从表头插入,将u插入到表头v
	u->next = g->adj[edge.v];
	g->adj[edge.v] = u;
	++g->e_num;
}

void graph_display(graph g)
{
	printf("%d vertices,%d edges\n", g->v_num, g->e_num);
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: ", g->vertex_array[i].str_vertex);
		for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {
			printf("%s ", g->vertex_array[x->key].str_vertex);
		}
		printf("\n");
	}
}

void graph_display_vertex(graph g)
{
	printf("各个顶点的数据:\n");
	for (int i = 0; i < g->v_num; i++) {
		printf("%s:%d\n", g->vertex_array[i].str_vertex,
		       g->vertex_array[i].dis);
	}
}

void graph_bfs(graph g, int s)
{
	for (int i = 0; i < g->v_num; i++) {
		if (i != s) {
			g->vertex_array[i].color = color_white;
			g->vertex_array[i].dis = INT_MAX;
			g->vertex_array[i].parent = -1;
		}
	}
	g->vertex_array[s].color = color_gray;
	g->vertex_array[s].dis = 0;
	g->vertex_array[s].parent = -1;
	queue q = queue_create();
	int *p = malloc(sizeof(int));
	*p = s;
	queue_en_queue(q, p);
	while (!queue_is_empty(q)) {
		p = queue_de_queue(q);
		int u = *p;
		free(p);
		for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {
			int v = x->key;
			if (g->vertex_array[v].color == color_white) {
				g->vertex_array[v].color = color_gray;
				g->vertex_array[v].dis =
				    g->vertex_array[u].dis + 1;
				g->vertex_array[v].parent = u;
				p = malloc(sizeof(int));
				*p = v;
				queue_en_queue(q, p);
			}
		}
		g->vertex_array[u].color = color_black;
	}
	queue_destroy(q, free);
}

void graph_print_path(graph g, int s, int v)
{
	if (v == s) {
		printf("%s ", g->vertex_array[s].str_vertex);
	} else {
		if (g->vertex_array[v].parent == -1) {
			printf("no path from %s to %s exist\n",
			       g->vertex_array[s].str_vertex,
			       g->vertex_array[v].str_vertex);
		} else {
			graph_print_path(g, s, g->vertex_array[v].parent);
			printf("%s ", g->vertex_array[v].str_vertex);
		}
	}
}

int main()
{
	//数据根据书上的图22-3
	char *str_vertex[8] = {
		"r", "s", "t", "u", "v", "w", "x", "y"
	};
	graph g = graph_create(8, str_vertex);
	struct edge edges[] = {
		{0, 1}, {0, 4}, {1, 5}, {2, 3}, {2, 5}, {2, 6}, {3, 6}, {3, 7},
		{5, 6}, {6, 7}
	};
	for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {
		graph_insert_edge(g, edges[i]);
	}
	graph_display(g);
	int s = 1;
	int v = 7;
	graph_bfs(g, s);
	graph_display_vertex(g);
	printf("path from %s to %s\n", str_vertex[s], str_vertex[v]);
	graph_print_path(g, s, v);
	printf("\n");
	graph_destroy(g);
}

22.3 深度优先搜索

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct graph_type *graph;
enum color_enum {
	color_white,
	color_gray,
	color_black
};
struct edge {
	int u;
	int v;
};
struct graph_node {
	int key;
	struct graph_node *next;
};
void graph_node_ini(struct graph_node *x, int key)
{
	x->key = key;
	x->next = NULL;
}

struct vertex {
	enum color_enum color;
	int parent;
	int discovered_time;
	int finish_time;
	char str_vertex[256];	//顶点的字符串表示,显示用
};
void vertex_ini(struct vertex *v)
{
	v->color = color_white;
	v->parent = -1;		//顶点编号是从0开始,-1表示一个不存在的结点
	v->discovered_time = 0;
	v->finish_time = 0;
	strcpy(v->str_vertex, "");
}

struct graph_type {
	struct graph_node **adj;
	int time;
	struct vertex *vertex_array;
	int v_num;
	int e_num;
};
//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用
graph graph_create(int v_num, char *str_vertex[])
{
	graph g = malloc(sizeof(struct graph_type));
	g->v_num = v_num;
	g->e_num = 0;
	g->time = 0;
	g->adj = malloc(sizeof(struct graph_node *) * v_num);
	g->vertex_array = malloc(sizeof(struct vertex) * v_num);
	for (int i = 0; i < v_num; i++) {
		g->adj[i] = NULL;
		strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);
	}
	return g;
}

void graph_destroy(graph g)
{
	for (int i = 0; i < g->v_num; i++) {
		for (struct graph_node * x = g->adj[i]; x != NULL;) {
			struct graph_node *del=x;
			x=x->next;
			free(del);
		}
	}
	free(g->adj);
	free(g->vertex_array);
	free(g);
}

void graph_insert_edge(graph g, struct edge edge)
{
	struct graph_node *v = malloc(sizeof(struct graph_node));
	graph_node_ini(v, edge.v);
	//从表头插入,将v插入到表头u
	v->next = g->adj[edge.u];
	g->adj[edge.u] = v;
	++g->e_num;
}

void graph_display(graph g)
{
	printf("%d vertices,%d edges\n", g->v_num, g->e_num);
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: ", g->vertex_array[i].str_vertex);
		for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {
			printf("%s ", g->vertex_array[x->key].str_vertex);
		}
		printf("\n");
	}
}

void graph_dfs_visit(graph g, int u)
{
	g->vertex_array[u].color = color_gray;
	g->vertex_array[u].discovered_time = ++g->time;
	for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {
		int v = x->key;
		if (g->vertex_array[v].color == color_white) {
			g->vertex_array[v].parent = u;
			graph_dfs_visit(g,v);
		}
	}
	g->vertex_array[u].color = color_black;
	g->vertex_array[u].finish_time = ++g->time;
}

void graph_depth_first_search(graph g)
{
	for (int i = 0; i < g->v_num; i++) {
		g->vertex_array[i].color = color_white;
		g->vertex_array[i].parent = -1;
	}
	for (int i = 0; i < g->v_num; i++) {
		if (g->vertex_array[i].color == color_white) {
			graph_dfs_visit(g,i);
		}
	}
}

void graph_display_vertex(graph g)
{
	printf("各个顶点的数据:\n");
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: %d/%d\n", g->vertex_array[i].str_vertex,
		       g->vertex_array[i].discovered_time,
		       g->vertex_array[i].finish_time);
	}
}

int main()
{
	//数据根据书上的图22-4
	char *str_vertex[6] = { "u", "v", "w", "x", "y", "z" };
	graph g=graph_create(6, str_vertex);
	struct edge edges[] =
	    { {0, 3}, {0, 1}, {1, 4}, {2, 4}, {2, 5}, {3, 1}, {4, 3}, {5, 5} };
	for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {
		graph_insert_edge(g,edges[i]);
	}
	graph_display(g);
	graph_depth_first_search(g);
	graph_display_vertex(g);
	graph_destroy(g);
	return 0;
}

22.4 拓扑排序

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct stack_type *stack;
struct stack_node {
	void *key;
	struct stack_node *next;
};
struct stack_type {
	struct stack_node *head;
};
void stack_node_ini(struct stack_node *n, void *key)
{
	n->key = key;
	n->next = NULL;
}

stack stack_create()
{
	stack s = malloc(sizeof(struct stack_type));
	s->head = NULL;
	return s;
}

bool stack_is_empty(stack s)
{
	return s->head == NULL;
}

void stack_push(stack s, void *x)
{
	struct stack_node *node = malloc(sizeof(struct stack_node));
	stack_node_ini(node, x);
	node->next = s->head;
	s->head = node;
}

void *stack_pop(stack s)
{
	struct stack_node *p = s->head;
	s->head = s->head->next;
	void *key = p->key;
	free(p);
	return key;
}

void stack_destroy(stack s, void (*free_key) (void *))
{
	while (!stack_is_empty(s)) {
		void *p = stack_pop(s);
		free_key(p);
	}
	free(s);
}

typedef struct graph_type *graph;
enum color_enum {
	color_white,
	color_gray,
	color_black
};
struct edge {
	int u;
	int v;
};
struct graph_node {
	int key;
	struct graph_node *next;
};
void graph_node_ini(struct graph_node *x, int key)
{
	x->key = key;
	x->next = NULL;
}

struct vertex {
	enum color_enum color;
	int parent;
	int discovered_time;
	int finish_time;
	char str_vertex[256];	//顶点的字符串表示,显示用
};
void vertex_ini(struct vertex *v)
{
	v->color = color_white;
	v->parent = -1;		//顶点编号是从0开始,-1表示一个不存在的结点
	v->discovered_time = 0;
	v->finish_time = 0;
	strcpy(v->str_vertex, "");
}

struct graph_type {
	struct graph_node **adj;
	int time;
	struct vertex *vertex_array;
	int v_num;
	int e_num;
};
//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用
graph graph_create(int v_num, char *str_vertex[])
{
	graph g = malloc(sizeof(struct graph_type));
	g->v_num = v_num;
	g->e_num = 0;
	g->time = 0;
	g->adj = malloc(sizeof(struct graph_node *) * v_num);
	g->vertex_array = malloc(sizeof(struct vertex) * v_num);
	for (int i = 0; i < v_num; i++) {
		g->adj[i] = NULL;
		strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);
	}
	return g;
}

void graph_destroy(graph g)
{
	for (int i = 0; i < g->v_num; i++) {
		for (struct graph_node * x = g->adj[i]; x != NULL;) {
			struct graph_node *del=x;
			x=x->next;
			free(del);
		}
	}
	free(g->adj);
	free(g->vertex_array);
	free(g);
}

void graph_insert_edge(graph g, struct edge edge)
{
	struct graph_node *v = malloc(sizeof(struct graph_node));
	graph_node_ini(v, edge.v);
	//从表头插入,将v插入到表头u
	v->next = g->adj[edge.u];
	g->adj[edge.u] = v;
	++g->e_num;
}

void graph_display(graph g)
{
	printf("%d vertices,%d edges\n", g->v_num, g->e_num);
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: ", g->vertex_array[i].str_vertex);
		for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {
			printf("%s ", g->vertex_array[x->key].str_vertex);
		}
		printf("\n");
	}
}

void graph_display_vertex(graph g)
{
	printf("各个顶点的数据:\n");
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: %d/%d\n", g->vertex_array[i].str_vertex,
		       g->vertex_array[i].discovered_time,
		       g->vertex_array[i].finish_time);
	}
}

void graph_dfs_visit(graph g, int u, stack s)
{
	g->vertex_array[u].color = color_gray;
	g->vertex_array[u].discovered_time = ++g->time;
	for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {
		int v = x->key;
		if (g->vertex_array[v].color == color_white) {
			g->vertex_array[v].parent = u;
			graph_dfs_visit(g, v, s);
		}
	}
	g->vertex_array[u].color = color_black;
	g->vertex_array[u].finish_time = ++g->time;
	int *p=malloc(sizeof(int));
	*p=u;
	stack_push(s, p);
}

//拓扑排序,把结果放到堆栈s,修改自depth_first_search函数
void graph_topological_sort(graph g,stack s)
{
	for (int i = 0; i < g->v_num; i++) {
		g->vertex_array[i].color = color_white;
		g->vertex_array[i].parent = -1;
	}
	for (int i = 0; i < g->v_num; i++) {
		if (g->vertex_array[i].color == color_white) {
			graph_dfs_visit(g,i, s);
		}
	}
}

int main()
{
	//数据根据书上的图22-7
	char *str_vertex[9] =
	    { "shirt", "tie", "jacket", "belt", "watch", "undershorts", "pants",
		"shoes", "socks"
	};
	graph g=graph_create(9, str_vertex);
	struct edge edges[] =
	    { {0, 3}, {0, 1}, {1, 2}, {3, 2}, {5, 7}, {5, 6}, {6, 7}, {6, 3},
	{8, 7}
	};
	for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {
		graph_insert_edge(g,edges[i]);
	}
	graph_display(g);
	stack s=stack_create();
	graph_topological_sort(g,s);
	graph_display_vertex(g);
	while (!stack_is_empty(s)) {
		int *p=stack_pop(s);		
		printf("%s ",str_vertex[*p]);
		free(p);
	}
	printf("\n");
	stack_destroy(s,free);
	graph_destroy(g);
	return 0;
}

22.5 强连通分支

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct stack_type *stack;
struct stack_node {
	void *key;
	struct stack_node *next;
};
struct stack_type {
	struct stack_node *head;
};
void stack_node_ini(struct stack_node *n, void *key)
{
	n->key = key;
	n->next = NULL;
}

stack stack_create()
{
	stack s = malloc(sizeof(struct stack_type));
	s->head = NULL;
	return s;
}

bool stack_is_empty(stack s)
{
	return s->head == NULL;
}

void stack_push(stack s, void *x)
{
	struct stack_node *node = malloc(sizeof(struct stack_node));
	stack_node_ini(node, x);
	node->next = s->head;
	s->head = node;
}

void *stack_pop(stack s)
{
	struct stack_node *p = s->head;
	s->head = s->head->next;
	void *key = p->key;
	free(p);
	return key;
}

void stack_destroy(stack s, void (*free_key) (void *))
{
	while (!stack_is_empty(s)) {
		void *p = stack_pop(s);
		free_key(p);
	}
	free(s);
}

typedef struct graph_type *graph;
enum color_enum {
	color_white,
	color_gray,
	color_black
};
struct edge {
	int u;
	int v;
};
struct graph_node {
	int key;
	struct graph_node *next;
};
void graph_node_ini(struct graph_node *x, int key)
{
	x->key = key;
	x->next = NULL;
}

struct vertex {
	enum color_enum color;
	int parent;
	int discovered_time;
	int finish_time;
	char str_vertex[256];	//顶点的字符串表示,显示用
};
void vertex_ini(struct vertex *v)
{
	v->color = color_white;
	v->parent = -1;		//顶点编号是从0开始,-1表示一个不存在的结点
	v->discovered_time = 0;
	v->finish_time = 0;
	strcpy(v->str_vertex, "");
}

struct graph_type {
	struct graph_node **adj;
	int time;
	struct vertex *vertex_array;
	int v_num;
	int e_num;
};
//顶点是编号为0~v_num-1的数,str_vertex是顶点的字符串表示,显示用
graph graph_create(int v_num, char *str_vertex[])
{
	graph g = malloc(sizeof(struct graph_type));
	g->v_num = v_num;
	g->e_num = 0;
	g->time = 0;
	g->adj = malloc(sizeof(struct graph_node *) * v_num);
	g->vertex_array = malloc(sizeof(struct vertex) * v_num);
	for (int i = 0; i < v_num; i++) {
		g->adj[i] = NULL;
		strcpy(g->vertex_array[i].str_vertex, str_vertex[i]);
	}
	return g;
}

void graph_destroy(graph g)
{
	for (int i = 0; i < g->v_num; i++) {
		for (struct graph_node * x = g->adj[i]; x != NULL;) {
			struct graph_node *del=x;
			x=x->next;
			free(del);
		}
	}
	free(g->adj);
	free(g->vertex_array);
	free(g);
}

void graph_insert_edge(graph g, struct edge edge)
{
	struct graph_node *v = malloc(sizeof(struct graph_node));
	graph_node_ini(v, edge.v);
	//从表头插入,将v插入到表头u
	v->next = g->adj[edge.u];
	g->adj[edge.u] = v;
	++g->e_num;
}

void graph_display(graph g)
{
	printf("%d vertices,%d edges\n", g->v_num, g->e_num);
	for (int i = 0; i < g->v_num; i++) {
		printf("%s: ", g->vertex_array[i].str_vertex);
		for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {
			printf("%s ", g->vertex_array[x->key].str_vertex);
		}
		printf("\n");
	}
}

void graph_dfs_visit(graph g, int u, stack s)
{
	g->vertex_array[u].color = color_gray;
	g->vertex_array[u].discovered_time = ++g->time;
	for (struct graph_node * x = g->adj[u]; x != NULL; x = x->next) {
		int v = x->key;
		if (g->vertex_array[v].color == color_white) {
			g->vertex_array[v].parent = u;
			graph_dfs_visit(g, v, s);
		}
	}
	g->vertex_array[u].color = color_black;
	g->vertex_array[u].finish_time = ++g->time;
	int *p = malloc(sizeof(int));
	*p = u;
	stack_push(s, p);
}

//拓扑排序,把结果放到堆栈s,修改自depth_first_search函数
void graph_topological_sort(graph g, stack s)
{
	for (int i = 0; i < g->v_num; i++) {
		g->vertex_array[i].color = color_white;
		g->vertex_array[i].parent = -1;
	}
	for (int i = 0; i < g->v_num; i++) {
		if (g->vertex_array[i].color == color_white) {
			graph_dfs_visit(g, i, s);
		}
	}
}

void graph_reverse_graph(graph g, graph gr)
{
	for (int i = 0; i < g->v_num; i++) {
		int u = i;
		for (struct graph_node * x = g->adj[i]; x != NULL; x = x->next) {
			int v = x->key;
			struct edge e = { v, u };
			graph_insert_edge(gr, e);
		}
	}
}

void strongly_connected_components(graph g, char *str_vertex[])
{
	stack s = stack_create();
	//第二次深度优先搜索是按拓扑排序的顺序来访问顶点,所以第一次深度优先搜索改成求拓扑排序
	graph_topological_sort(g, s);
	graph gr = graph_create(g->v_num, str_vertex);
	graph_reverse_graph(g, gr);	//根据原图构造转置图
	stack sr = stack_create();
	for (int i = 0; i < g->v_num; i++) {
		gr->vertex_array[i].color = color_white;
		gr->vertex_array[i].parent = -1;
	}
	printf("图的强连通分支如下:\n");
	int i = 0;
	while (!stack_is_empty(s)) {
		int *p = stack_pop(s);
		int u = *p;
		free(p);
		if (gr->vertex_array[u].color == color_white) {
			graph_dfs_visit(gr, u, sr);	//sr记录了一个连通分支的所有结点
			printf("第%d个连通分支:\n", i + 1);
			while (!stack_is_empty(sr)) {
				int *p = stack_pop(sr);
				printf("%s ", gr->vertex_array[*p].str_vertex);
				free(p);
			}
			printf("\n");
			++i;
		}
	}
	stack_destroy(s,free);
	stack_destroy(sr,free);
	graph_destroy(gr);
}

int main()
{
	//数据根据书上的图22-9
	char *str_vertex[8] = { "c", "d", "h", "g", "b", "f", "e", "a" };
	graph g = graph_create(8, str_vertex);
	struct edge edges[] = {
		{0, 1}, {0, 3}, {1, 0}, {1, 2}, {2, 2}, {3, 2}, {3, 5}, {4, 0},
		{4, 5}, {4, 6}, {5, 3}, {6, 5}, {6, 7}, {7, 4}
	};
	for (unsigned i = 0; i < sizeof(edges) / sizeof(edges[0]); i++) {
		graph_insert_edge(g, edges[i]);
	}
	graph_display(g);
	strongly_connected_components(g, str_vertex);
	graph_destroy(g);
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值