lwfree(ids_by_cluster);
}
+static void test_unionfind_path_compression(void)
+{
+ UNIONFIND* uf = UF_create(5);
+ uint32_t i;
+
+ uf->clusters[1] = 0;
+ uf->clusters[2] = 1;
+ uf->clusters[3] = 2;
+ uf->clusters[4] = 3;
+
+ /* Calling "find" on a leaf should attach all nodes between the root and the
+ * leaf directly to the root. */
+ uint32_t root = UF_find(uf, 4);
+ for (i = 0; i < uf->N; i++)
+ {
+ /* Verify that all cluster references have been updated to point
+ * directly to the root. */
+ CU_ASSERT_EQUAL(root, uf->clusters[i]);
+ }
+
+ UF_destroy(uf);
+}
+
void unionfind_suite_setup(void);
void unionfind_suite_setup(void)
{
PG_ADD_TEST(suite, test_unionfind_create);
PG_ADD_TEST(suite, test_unionfind_union);
PG_ADD_TEST(suite, test_unionfind_ordered_by_cluster);
+ PG_ADD_TEST(suite, test_unionfind_path_compression);
}
if ((i == num_geoms - 1) ||
(UF_find(uf, ordered_components[i]) != UF_find(uf, ordered_components[i+1])))
{
+ if (k >= uf->num_clusters) {
+ /* Should not get here - it means that we have more clusters than uf->num_clusters thinks we should. */
+ return LW_FAILURE;
+ }
+
if (is_lwgeom)
{
- LWGEOM** components = lwalloc(num_geoms * sizeof(LWGEOM*));
- memcpy(components, geoms_in_cluster, num_geoms * sizeof(LWGEOM*));
+ LWGEOM** components = lwalloc(j * sizeof(LWGEOM*));
+ memcpy(components, geoms_in_cluster, j * sizeof(LWGEOM*));
(*clusterGeoms)[k++] = lwcollection_construct(COLLECTIONTYPE, components[0]->srid, NULL, j, (LWGEOM**) components);
}
else
uint32_t
UF_find (UNIONFIND* uf, uint32_t i)
{
- while (uf->clusters[i] != i)
- {
- uf->clusters[i] = uf->clusters[uf->clusters[i]];
- i = uf->clusters[i];
+ uint32_t base = i;
+ while (uf->clusters[base] != base) {
+ base = uf->clusters[base];
+ }
+
+ while (i != base) {
+ uint32_t next = uf->clusters[i];
+ uf->clusters[i] = base;
+ i = next;
}
+
return i;
}