diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/support/disjoint_sets.h | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/support/disjoint_sets.h b/src/support/disjoint_sets.h new file mode 100644 index 000000000..198e5cb67 --- /dev/null +++ b/src/support/disjoint_sets.h @@ -0,0 +1,87 @@ +/* + * Copyright 2024 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef wasm_support_disjoint_sets_h +#define wasm_support_disjoint_sets_h + +#include <cassert> +#include <cstddef> +#include <vector> + +namespace wasm { + +// A disjoint set forest (a.k.a. union-find) implementation. See +// https://en.wikipedia.org/wiki/Disjoint-set_data_structure. +struct DisjointSets { + struct ElemInfo { + // The index of the parent element, or the index of the element itself if it + // has no parent. + size_t parent; + // An upper bound on the height of the tree rooted at this element. + size_t rank; + }; + std::vector<ElemInfo> info; + + // Add an element and return its index. + size_t addSet() { + size_t ret = info.size(); + info.push_back({ret, 0}); + return ret; + } + + // Get the representative element of the set to which `elem` belongs. + size_t getRoot(size_t elem) { + assert(elem < info.size()); + size_t root = elem; + // Follow parent pointers up to the root. + for (; info[root].parent != root; root = info[root].parent) { + } + // Compress the path to make subsequent getRoots of this set faster. + while (elem != root) { + size_t parent = info[elem].parent; + info[elem].parent = root; + elem = parent; + } + return root; + } + + // Join the sets to which the elements belong and return the representative + // element of the union. + size_t getUnion(size_t elem1, size_t elem2) { + assert(elem1 < info.size() && elem2 < info.size()); + size_t root1 = getRoot(elem1); + size_t root2 = getRoot(elem2); + if (root1 == root2) { + // Already in the same set. + return root1; + } + // Canonicalize so that root1 has the greater rank. + if (info[root1].rank < info[root2].rank) { + std::swap(root1, root2); + } + // Merge the trees, smaller into larger. + info[root2].parent = root1; + // If the ranks were equal, the new root has a larger rank. + if (info[root1].rank == info[root2].rank) { + ++info[root1].rank; + } + return root1; + } +}; + +} // namespace wasm + +#endif // wasm_support_disjoint_sets_h |