第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);
}