Skip to content

Commit b4f9778

Browse files
committed
sys: Add Disjoint-set data structure
Add a set of Disjoint-set functions (`find`, `union`) to handle queries between sets. Signed-off-by: James Roy <[email protected]>
1 parent ddc43f0 commit b4f9778

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

doc/releases/release-notes-4.3.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ New APIs and options
6565
6666
.. zephyr-keep-sorted-start re(^\* \w)
6767
68+
69+
* Utilities
70+
71+
* :c:struct:`sys_set_node`
72+
* :c:func:`sys_set_makeset`
73+
* :c:func:`sys_set_find`
74+
* :c:func:`sys_set_union`
75+
6876
.. zephyr-keep-sorted-stop
6977
7078
New Boards

include/zephyr/sys/set.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2025 James Roy <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @defgroup union_find_apis Disjoint-set
10+
* @ingroup datastructure_apis
11+
*
12+
* @brief Disjoint-set implementation
13+
*
14+
* This implements a disjoint-set (union-find) that guarantees
15+
* O(alpha(n)) runtime for all operations. The algorithms and
16+
* naming are conventional per existing academic and didactic
17+
* implementations, c.f.:
18+
*
19+
* https://en.wikipedia.org/wiki/Disjoint-set_data_structure
20+
*
21+
* @{
22+
*/
23+
24+
#ifndef ZEPHYR_INCLUDE_SYS_SET_H_
25+
#define ZEPHYR_INCLUDE_SYS_SET_H_
26+
27+
#include <stdint.h>
28+
29+
/**
30+
* @brief Disjoint-set node structure
31+
*/
32+
struct sys_set_node {
33+
/** @cond INTERNAL_HIDDEN */
34+
struct sys_set_node *parent;
35+
uint16_t rank;
36+
/** @endcond */
37+
};
38+
39+
/**
40+
* @brief Initialize a disjoint-set.
41+
*
42+
* @param node Pointer to a sys_set_node structure.
43+
*/
44+
static inline void sys_set_makeset(struct sys_set_node *node)
45+
{
46+
node->parent = node;
47+
node->rank = 0;
48+
}
49+
50+
/**
51+
* @brief Find the root of the disjoint-set.
52+
*
53+
* @param node Pointer to a sys_set_node structure.
54+
* @return Pointer to the root sys_set_node of the set containing the @p node.
55+
*/
56+
struct sys_set_node *sys_set_find(struct sys_set_node *node);
57+
58+
/**
59+
* @brief Merge two nodes into the same disjoint-set.
60+
*
61+
* This function attaches the node with the smaller rank to the one with the
62+
* larger rank. That say, if @p node1 has a smaller rank than @p node2, it will
63+
* be linked to @p node2.
64+
*
65+
* @param node1 Pointer to a sys_set_node structure.
66+
* @param node2 Pointer to a sys_set_node structure.
67+
*/
68+
void sys_set_union(struct sys_set_node *node1, struct sys_set_node *node2);
69+
70+
/** @} */
71+
72+
#endif /* ZEPHYR_INCLUDE_SYS_SET_H_ */

lib/utils/set.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright (c) 2025 James Roy <[email protected]>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/sys/set.h>
8+
9+
struct sys_set_node *sys_set_find(struct sys_set_node *node)
10+
{
11+
struct sys_set_node *parent;
12+
13+
while (node != node->parent) {
14+
parent = node->parent;
15+
node->parent = parent->parent;
16+
node = parent;
17+
}
18+
19+
return node;
20+
}
21+
22+
void sys_set_union(struct sys_set_node *node1, struct sys_set_node *node2)
23+
{
24+
struct sys_set_node *root1 = sys_set_find(node1);
25+
struct sys_set_node *root2 = sys_set_find(node2);
26+
27+
if (root1 == root2) {
28+
return;
29+
}
30+
31+
if (root1->rank < root2->rank) {
32+
root1->parent = root2;
33+
} else if (root1->rank > root2->rank) {
34+
root2->parent = root1;
35+
} else {
36+
root2->parent = root1;
37+
root1->rank++;
38+
}
39+
}

0 commit comments

Comments
 (0)