-
Notifications
You must be signed in to change notification settings - Fork 274
/
bfs.c
136 lines (87 loc) · 2.7 KB
/
bfs.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//
// bfs.c
// Algorithms - Graph breadth-first search
//
// Created by YourtionGuo on 08/05/2017.
// Copyright © 2017 Yourtion. All rights reserved.
//
#include <stdlib.h>
#include "bfs.h"
#include "graph.h"
#include "list.h"
#include "queue.h"
#pragma mark - Public
int bfs(Graph *graph, BfsVertex *start, List *hops)
{
Queue queue;
AdjList *adjlist, *clr_adjlist;
BfsVertex *clr_vertex, *adj_vertex;
ListElmt *element, *member;
/// 初始化图的所有顶点
for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) {
clr_vertex = ((AdjList *)list_data(element))->vertex;
if (graph->match(clr_vertex, start)) {
/// 初始化起点
clr_vertex->color = gray;
clr_vertex->hops = 0;
} else {
/// 初始化其他顶点
clr_vertex->color = white;
clr_vertex->hops = -1;
}
}
/// 根据起点邻接表初始化队列
queue_init(&queue, NULL);
if (graph_adjlist(graph, start, &clr_adjlist) != 0) {
queue_destroy(&queue);
return -1;
}
if (queue_enqueue(&queue, clr_adjlist) != 0) {
queue_destroy(&queue);
return -1;
}
/// 执行广度优先搜索
while (queue_size(&queue) > 0) {
adjlist = queue_peek(&queue);
/// 在当前邻接表遍历每个顶点
for (member = list_head(&adjlist->adjacent); member != NULL; member = list_next(member)) {
adj_vertex = list_data(member);
/// 确定下个邻接顶点的颜色
if (graph_adjlist(graph, adj_vertex, &clr_adjlist) != 0) {
queue_destroy(&queue);
return -1;
}
clr_vertex = clr_adjlist->vertex;
/// 将白顶点着色为灰色并将邻接表入队
if (clr_vertex->color == white) {
clr_vertex->color = gray;
clr_vertex->hops = ((BfsVertex *)adjlist->vertex)->hops + 1;
if (queue_enqueue(&queue, clr_adjlist) != 0) {
queue_destroy(&queue);
return -1;
}
}
}
/// 将当前邻接表出队并将其着色为黑色
if (queue_dequeue(&queue, (void **)&adjlist) == 0) {
((BfsVertex *)adjlist->vertex)->color = black;
} else {
queue_destroy(&queue);
return -1;
}
}
queue_destroy(&queue);
/// 回传每个顶点的跳数到表中
list_init(hops, NULL);
for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) {
/// 去掉跳数为 -1 的(不可达)
clr_vertex = ((AdjList *)list_data(element))->vertex;
if (clr_vertex->hops != -1) {
if (list_ins_next(hops, list_tail(hops), clr_vertex) != 0) {
list_destroy(hops);
return -1;
}
}
}
return 0;
}