GEOS  3.14.0dev
UnionFind.h
1 /**********************************************************************
2  *
3  * GEOS - Geometry Engine Open Source
4  * http://geos.osgeo.org
5  *
6  * Copyright (C) 2020-2021 Daniel Baston
7  *
8  * This is free software; you can redistribute and/or modify it under
9  * the terms of the GNU Lesser General Public Licence as published
10  * by the Free Software Foundation.
11  * See the COPYING file for more information.
12  *
13  **********************************************************************/
14 
15 #pragma once
16 
17 #include <algorithm>
18 #include <numeric>
19 #include <vector>
20 
21 #include <geos/export.h>
22 #include <geos/operation/cluster/Clusters.h>
23 
24 namespace geos {
25 namespace operation {
26 namespace cluster {
27 
32 class GEOS_DLL UnionFind {
33 
34 public:
39  explicit UnionFind(size_t n) :
40  clusters(n),
41  sizes(n),
42  num_clusters(n) {
43  std::iota(clusters.begin(), clusters.end(), 0);
44  std::fill(sizes.begin(), sizes.end(), 1);
45  }
46 
47  // Are two elements in the same cluster?
48  bool same(size_t i, size_t j) {
49  return i == j || (find(i) == find(j));
50  }
51 
52  // Are two elements in a different cluster?
53  bool different(size_t i, size_t j) {
54  return !same(i, j);
55  }
56 
62  size_t find(size_t i) {
63  size_t root = i;
64 
65  while(clusters[root] != root) {
66  root = clusters[root];
67  }
68 
69  while (i != root) {
70  size_t next = clusters[i];
71  clusters[i] = root;
72  i = next;
73  }
74 
75  return i;
76  }
77 
83  void join(size_t i, size_t j) {
84  auto a = find(i);
85  auto b = find(j);
86 
87  if (a == b) {
88  return;
89  }
90 
91  if ((sizes[b] > sizes[a]) || (sizes[a] == sizes[b] && b <= a)) {
92  std::swap(a, b);
93  }
94 
95  clusters[a] = clusters[b];
96  sizes[b] += sizes[a];
97  sizes[a] = 0;
98 
99  num_clusters--;
100  }
101 
102  size_t getNumClusters() const {
103  return num_clusters;
104  }
105 
106  template<typename T>
107  void sortByCluster(T begin, T end) {
108  std::sort(begin, end, [this](size_t a, size_t b) {
109  return find(a) < find(b);
110  });
111  }
112 
117  Clusters getClusters();
118 
124  Clusters getClusters(std::vector<size_t> elems);
125 
126 private:
127  std::vector<size_t> clusters;
128  std::vector<size_t> sizes;
129  size_t num_clusters;
130 };
131 
132 }
133 }
134 }
Definition: UnionFind.h:32
Clusters getClusters(std::vector< size_t > elems)
UnionFind(size_t n)
Definition: UnionFind.h:39
size_t find(size_t i)
Definition: UnionFind.h:62
void join(size_t i, size_t j)
Definition: UnionFind.h:83
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25