-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathmst.c
129 lines (86 loc) · 2.95 KB
/
mst.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
//
// mst.c
// Algorithms - Minimum spanning tree
//
// Created by YourtionGuo on 23/05/2017.
// Copyright © 2017 Yourtion. All rights reserved.
//
#include <float.h>
#include <stdlib.h>
#include "graph.h"
#include "graphalg.h"
#include "list.h"
int mst(Graph *graph, const MstVertex *start, List *span,
int (*match)(const void *key1, const void *key2))
{
AdjList *adjlist = NULL;
MstVertex *mst_vertex, *adj_vertex;
ListElmt *element, *member;
double minimum;
int found, i;
/// 初始化图的所有顶点
found = 0;
for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) {
mst_vertex = ((AdjList *)list_data(element))->vertex;
if (match(mst_vertex, start)) {
/// 初始化起点
mst_vertex->color = white;
mst_vertex->key = 0;
mst_vertex->parent = NULL;
found = 1;
} else {
/// 初始化起点外的其他顶点
mst_vertex->color = white;
mst_vertex->key = DBL_MAX;
mst_vertex->parent = NULL;
}
}
/// 如果找不到起点返回 -1
if (!found) return -1;
/// 使用 Prim 算法计算最小生成树
i = 0;
while (i < graph_vcount(graph)) {
/// 选择最小权重的白色顶点
minimum = DBL_MAX;
for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) {
mst_vertex = ((AdjList *)list_data(element))->vertex;
if (mst_vertex->color == white && mst_vertex->key < minimum) {
minimum = mst_vertex->key;
adjlist = list_data(element);
}
}
/// 将选中的顶点涂为黑色
((MstVertex *)adjlist->vertex)->color = black;
/// 遍历选中顶点的每个邻接顶点
for (member = list_head(&adjlist->adjacent); member != NULL; member = list_next(member)) {
adj_vertex = list_data(member);
/// 通过顶点的邻接表找到邻接顶点
for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) {
mst_vertex = ((AdjList *)list_data(element))->vertex;
if (match(mst_vertex, adj_vertex)) {
/// 决定是否改变邻接表中邻接顶点的权重和父节点
if (mst_vertex->color == white && adj_vertex->weight < mst_vertex->key) {
mst_vertex->key = adj_vertex->weight;
mst_vertex->parent = adjlist->vertex;
}
break;
}
}
}
/// 准备选择下一个顶点
i++;
}
/// 将最小生成树载入列表
list_init(span, NULL);
for (element = list_head(&graph_adjlists(graph)); element != NULL; element = list_next(element)) {
/// 从邻接表中加载每个黑色顶点
mst_vertex = ((AdjList *)list_data(element))->vertex;
if (mst_vertex->color == black) {
if (list_ins_next(span, list_tail(span), mst_vertex) != 0) {
list_destroy(span);
return -1;
}
}
}
return 0;
}