GEOS  3.13.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 #ifndef GEOS_OPERATION_CLUSTER_UNIONFIND
16 #define GEOS_OPERATION_CLUSTER_UNIONFIND
17 
18 #include <algorithm>
19 #include <numeric>
20 #include <vector>
21 
22 #include <geos/export.h>
23 #include <geos/operation/cluster/Clusters.h>
24 
25 namespace geos {
26 namespace operation {
27 namespace cluster {
28 
33 class GEOS_DLL UnionFind {
34 
35 public:
40  explicit UnionFind(size_t n) :
41  clusters(n),
42  sizes(n),
43  num_clusters(n) {
44  std::iota(clusters.begin(), clusters.end(), 0);
45  std::fill(sizes.begin(), sizes.end(), 1);
46  }
47 
48  // Are two elements in the same cluster?
49  bool same(size_t i, size_t j) {
50  return i == j || (find(i) == find(j));
51  }
52 
53  // Are two elements in a different cluster?
54  bool different(size_t i, size_t j) {
55  return !same(i, j);
56  }
57 
63  size_t find(size_t i) {
64  size_t root = i;
65 
66  while(clusters[root] != root) {
67  root = clusters[root];
68  }
69 
70  while (i != root) {
71  size_t next = clusters[i];
72  clusters[i] = root;
73  i = next;
74  }
75 
76  return i;
77  }
78 
84  void join(size_t i, size_t j) {
85  auto a = find(i);
86  auto b = find(j);
87 
88  if (a == b) {
89  return;
90  }
91 
92  if ((sizes[b] > sizes[a]) || (sizes[a] == sizes[b] && b <= a)) {
93  std::swap(a, b);
94  }
95 
96  clusters[a] = clusters[b];
97  sizes[b] += sizes[a];
98  sizes[a] = 0;
99 
100  num_clusters--;
101  }
102 
103  size_t getNumClusters() const {
104  return num_clusters;
105  }
106 
107  template<typename T>
108  void sortByCluster(T begin, T end) {
109  std::sort(begin, end, [this](size_t a, size_t b) {
110  return find(a) < find(b);
111  });
112  }
113 
118  Clusters getClusters();
119 
125  Clusters getClusters(std::vector<size_t> elems);
126 
127 private:
128  std::vector<size_t> clusters;
129  std::vector<size_t> sizes;
130  size_t num_clusters;
131 };
132 
133 }
134 }
135 }
136 
137 #endif
Definition: UnionFind.h:33
Clusters getClusters(std::vector< size_t > elems)
UnionFind(size_t n)
Definition: UnionFind.h:40
size_t find(size_t i)
Definition: UnionFind.h:63
void join(size_t i, size_t j)
Definition: UnionFind.h:84
Basic namespace for all GEOS functionalities.
Definition: Angle.h:25