forked from TheAlgorithms/C
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprim.c
203 lines (175 loc) · 4.7 KB
/
prim.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/**
* @file
* @author [Timothy Maloney](https://github.com/sl1mb0)
* @brief [Prim's algorithm](https://en.wikipedia.org/wiki/Prim%27s_algorithm)
* implementation in C to find the MST of a weighted, connected graph.
* @details Prim's algorithm uses a greedy approach to generate the MST of a weighted connected graph.
* The algorithm begins at an arbitrary vertex v, and selects a next vertex u,
* where v and u are connected by a weighted edge whose weight is the minimum of all edges connected to v.
* @references Page 319 "Introduction to the Design and Analysis of Algorithms" - Anany Levitin
*
* To test - run './prim -test'
* prim() will find the MST of the following adj. matrix:
*
* 0 1 2 3
* 1 0 4 6
* 2 4 0 5
* 3 6 5 0
*
* The minimum spanning tree for the above weighted connected graph is given by the following adj matrix:
*
* 0 1 2 3
* 1 0 0 0
* 2 0 0 0
* 3 0 0 0
*
*
* The following [link](https://visualgo.net/en/mst) provides a visual representation of graphs that can be used to test/verify the algorithm for different adj
* matrices and their weighted, connected graphs.
*/
#include <stdio.h> /// for IO operations
#include <string.h> /// for string comparison
#include <assert.h> /// for assert()
#include <inttypes.h> /// for uint16_t
#define MAX 20
#define INF 999
/**
* @brief Finds index of minimum element in edge list for an arbitrary vertex
* @param arr graph row
* @param N number of elements in arr
* @returns index of minimum element in arr
*/
uint16_t minimum(uint16_t arr[], uint16_t N)
{
uint16_t index = 0;
uint16_t min = INF;
for (uint16_t i = 0; i < N; i++)
{
if (arr[i] < min)
{
min = arr[i];
index = i;
}
}
return index;
}
/**
* @brief Used to find MST of user-generated adj matrix G
* @returns void
*/
void prim(uint16_t G[][MAX], uint16_t MST[][MAX], uint16_t V)
{
uint16_t u, v;
uint16_t E_t[MAX], path[MAX];
uint16_t V_t[MAX], no_of_edges;
E_t[0] = 0; // edges for current vertex
V_t[0] = 1; // list of visited vertices
for (uint16_t i = 1; i < V; i++)
{
E_t[i] = G[i][0];
path[i] = 0;
V_t[i] = 0;
}
no_of_edges = V - 1;
while (no_of_edges > 0)
{
u = minimum(E_t, V);
while (V_t[u] == 1)
{
E_t[u] = INF;
u = minimum(E_t, V);
}
v = path[u];
MST[v][u] = E_t[u];
MST[u][v] = E_t[u];
no_of_edges--;
V_t[u] = 1;
for (uint16_t i = 1; i < V; i++)
{
if (V_t[i] == 0 && G[u][i] < E_t[i])
{
E_t[i] = G[u][i];
path[i] = v;
}
}
}
}
/**
* @brief Self-test implementations
* @returns void
*/
static void test(uint16_t G[][MAX], uint16_t MST[][MAX], uint16_t V)
{
uint16_t test[4][4] = {{0,1,2,3},{1,0,4,6},{2,4,0,5},{3,6,5,0}};
uint16_t solution[4][4] = {{0,1,2,3},{1,0,0,0},{2,0,0,0},{3,0,0,0}};
V = 4;
for(uint16_t i = 0; i < V; ++i)
{
for(uint16_t j = 0; j < V; ++j)
{
G[i][j] = test[i][j];
}
}
prim(&(*G),&(*MST),V);
for(uint16_t i = 0; i < V; ++i)
{
for(uint16_t j = 0; j < V; ++j)
{
assert(MST[i][j] == solution[i][j]);
}
}
}
/**
* @brief Function user_graph();
* gets user input adj. matrix and finds MST of that graph
* @returns void
*/
void user_graph(uint16_t G[][MAX], uint16_t MST[][MAX], uint16_t V)
{
printf("Enter the number of vertices: ");
scanf(" %hd", &V);
assert(V <= MAX);
printf("Enter the adj matrix\n");
uint16_t i, j;
for (i = 0; i < V; ++i)
{
for (j = 0; j < V; ++j)
{
printf("G[%d][%d]: ", i, j);
scanf(" %hd", &G[i][j]);
if (G[i][j] == 0)
G[i][j] = INF;
}
}
prim(&(*G),&(*MST),V);
printf("minimum spanning tree:\n");
for (i = 0; i < V; ++i)
{
printf("\n");
for (j = 0; j < V; ++j)
{
printf("%d\t", MST[i][j]);
}
}
}
/**
* @brief Main function
* @param argc commandline argument count (ignored)
* @param argv commandline array of arguments (ignored)
* @returns 0 on exit
*/
int main(int argc, char const *argv[])
{
uint16_t G[MAX][MAX]; ///< weighted, connected graph G
uint16_t MST[MAX][MAX]; ///< adj matrix to hold minimum spanning tree of G
uint16_t V; ///< number of vertices in V in G
if(argc == 2 && strcmp(argv[1],"-test") == 0)
{
test(&(*G),&(*MST),V);
}
else
{
user_graph(&(*G),&(*MST),V);
}
return 0;
}