Skip to content

Commit d809da7

Browse files
committed
feat: add graph_kruskal
1 parent c7ad70d commit d809da7

File tree

7 files changed

+62
-15
lines changed

7 files changed

+62
-15
lines changed

src/graph/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ INCLUDE := -I../ -L../list/single -L../hash-table -L../set -L../queue -L../stac
1414

1515
# targets to compile
1616
TEST_TARGET = test
17-
TARGETS = graph.o bfs.o dfs.o acyclical.o tarjan.o dijkstra.o
17+
TARGETS = graph.o bfs.o dfs.o acyclical.o tarjan.o dijkstra.o kruskal.o
1818
LIBRARY_OBJS = $(TARGETS)
1919

2020
TEST_BINARY = $(TEST_TARGET).$(EXTENSION)

src/graph/graph.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,14 @@ List* graph_topological_sort(Graph *g);
273273
*/
274274
Graph* graph_dijkstra(Graph* g, int source);
275275

276+
/**
277+
* @brief Run kruskal algorithm to get the minimum-span tree.
278+
* @param g The graph to traverse.
279+
* @return a new graph with the minimum span tree.
280+
* @ingroup DataStructureMethods
281+
*/
282+
Graph* graph_kruskal(Graph* g);
283+
276284
/**
277285
* @brief Run dijkstra algorithm and calculate the minimum distance.
278286
* @param g The graph to traverse.

src/graph/kruskal.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "graph.h"
2+
#include "../set/set-disjoint.h"
3+
4+
Graph* graph_kruskal(Graph *g) {
5+
Graph *g_kruskal = graph_create();
6+
DisjointSet *components = set_disjoint_create(graph_max_node_id(g) + 1);
7+
List *edges = graph_edges_ordered(g);
8+
Iterator *it = list_iterator(edges);
9+
10+
while (!iterator_done(it)) {
11+
List *edge = (List*) iterator_next(it);
12+
int u = edge->key;
13+
int v = edge->data;
14+
if (set_disjoint_find(components, u) != set_disjoint_find(components, v)) {
15+
graph_add_edge_with_weight(g_kruskal, u, v, graph_get_edge_weight(g, u, v));
16+
set_disjoint_union(components, u, v);
17+
}
18+
}
19+
20+
set_disjoint_free(components);
21+
iterator_free(it);
22+
list_free(edges);
23+
return g_kruskal;
24+
}

src/graph/test.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,27 @@ void test_graph_dijkstra(bool extra_tests) {
389389
graph_free(dijkstra_result);
390390
}
391391

392+
void test_graph_kruskal() {
393+
puts("== Graph kruskal test");
394+
Graph *g = graph_create();
395+
graph_add_edge_with_weight(g, 1, 2, 10);
396+
graph_add_edge_with_weight(g, 1, 3, 20);
397+
graph_add_edge_with_weight(g, 2, 3, 5);
398+
graph_add_edge_with_weight(g, 3, 4, 30);
399+
graph_add_edge_with_weight(g, 4, 1, 9);
400+
graph_add_edge_with_weight(g, 5, 1, 7);
401+
402+
printf(":: input graph\n");
403+
graph_print(g);
404+
405+
printf(":: kruskal tree\n");
406+
Graph *g_kruskal = graph_kruskal(g);
407+
graph_print(g_kruskal);
408+
409+
graph_free(g);
410+
graph_free(g_kruskal);
411+
}
412+
392413

393414
bool should_run_extra_tests(int argc, char *argv[]) {
394415
// Iterate through the command-line arguments starting from argv[1]
@@ -413,6 +434,7 @@ int main(int argc, char *argv[]) {
413434
test_graph_topological_sort();
414435
test_graph_dijkstra(extra_tests);
415436
test_graph_edges_ordered();
437+
test_graph_kruskal();
416438
if (should_run_extra_tests(argc, argv)) {
417439
test_graph_export();
418440
}

src/set/set-disjoint.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,10 @@ DisjointSet *set_disjoint_create(int n) {
2323
return ds;
2424
}
2525

26-
void set_disjoint_destroy(DisjointSet **ds) {
27-
if (ds == NULL || *ds == NULL) {
28-
return;
29-
}
30-
free((*ds)->parent);
31-
(*ds)->parent = NULL;
32-
free((*ds)->rank);
33-
(*ds)->rank = NULL;
34-
free(*ds);
35-
*ds = NULL;
26+
void set_disjoint_free(DisjointSet *ds) {
27+
free(ds->parent);
28+
free(ds->rank);
29+
free(ds);
3630
}
3731

3832
// Find with path compression

src/set/set-disjoint.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ typedef struct DisjointSet DisjointSet;
1616
DisjointSet *set_disjoint_create(int n);
1717

1818
/**
19-
* @brief Destroys a disjoint-set data structure.
19+
* @brief Free a disjoint-set data structure.
2020
*
2121
* @param[in,out] ds A pointer to a pointer to the disjoint-set.
2222
*/
23-
void set_disjoint_destroy(DisjointSet **ds);
23+
void set_disjoint_free(DisjointSet *ds);
2424

2525
/**
2626
* @brief Finds the representative of the set containing element i.

src/set/test.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,7 @@ void test_set_disjoint() {
183183
assert(set_disjoint_find(ds, 8) == set_disjoint_find(ds, 9));
184184
assert(set_disjoint_find(ds, 0) != set_disjoint_find(ds, 8));
185185

186-
set_disjoint_destroy(&ds);
187-
assert(ds == NULL);
186+
set_disjoint_free(ds);
188187
}
189188

190189

0 commit comments

Comments
 (0)