unsigned int graph_connected_components(graph_t g) { unsigned int classes_count = 0, n, m, left, right; union_find_t uf; edge_t *edges; n = graph_vertices_count(g); m = graph_edges_count(g); uf = union_find_create(n); edges = graph_edges(g); for (unsigned int i = 0; i < m; i++) { left = vertex_label(edge_left_vertex(edges[i])); right = vertex_label(edge_right_vertex(edges[i])); left = union_find_find(uf, left); right = union_find_find(uf, right); if (!union_find_connected(uf, left, right)) { union_find_union(uf, left, right); } edges[i] = edge_destroy(edges[i]); } free(edges); classes_count = union_find_count(uf); uf = union_find_destroy(uf); return (classes_count); }
/* TODO merge with 2D version */ struct MergeTree *compute_merge_tree3d(const struct CtGrid3d *grid, const struct Scalar sorted_scalars[], int8_t lookup[][3], const int lookup_size) { /* TODO do sanity checks if memory could be allocated */ struct UnionFind *uf = union_find_create(grid->len); /* lowest vertex of each component */ int *lowest_vertex = malloc(grid->len * sizeof(int)); struct MergeTree *tree = merge_tree_create(grid->len); /* set global maximum */ if (grid->len) tree->max_node = sorted_scalars[0].index; const struct Header *header = grid3d_header(grid); for (int i = 0; i < grid->len; ++i) { const int v = sorted_scalars[i].index; int v_i, v_j, v_k; grid3d_index2pos(grid, v, &v_i, &v_j, &v_k); int uf_v = union_find_make_set(uf, v); merge_tree_add_node(tree, v, sorted_scalars[i].isovalue); /* check all neighbours */ for (int j = 0; j < lookup_size; ++j) { const int n_i = v_i + lookup[j][0]; const int n_j = v_j + lookup[j][1]; const int n_k = v_k + lookup[j][2]; const int n = grid3d_pos2index(grid, n_i, n_j, n_k); int uf_n; /* check for boundary or if vertex was already processed */ if ((n_i < 0 || n_i >= header->size[0]) || (n_j < 0 || n_j >= header->size[1]) || (n_k < 0 || n_k >= header->size[2]) || (uf_n = union_find_find(uf, n)) == UNION_FIND_NULL) continue; /* different components; merge and add arc to tree */ if (uf_n != uf_v) { merge_tree_add_arc(tree, v, lowest_vertex[uf_n], n); uf_v = union_find_union(uf, uf_v, uf_n); } } /* we have latest set for vertex v, because union operation returns it */ lowest_vertex[uf_v] = v; } union_find_destroy(uf); free(lowest_vertex); return tree; }
graph_t kruskal(graph_t graph) { graph_t result = graph_empty(graph_vertices_count(graph)); unsigned int L, R, num_edges = graph_edges_count(graph); vertex_t l = NULL, r = NULL; pqueue_t Q = pqueue_empty(num_edges); union_find_t C = union_find_create(graph_vertices_count(graph)); edge_t E = NULL, *edges = graph_edges(graph); for (unsigned int i = 0; i < num_edges; i++) { pqueue_enqueue(Q, edges[i]); } free(edges); edges = NULL; while (!pqueue_is_empty(Q) && union_find_count(C) > 1) { E = edge_copy(pqueue_fst(Q)); l = edge_left_vertex(E); r = edge_right_vertex(E); L = union_find_find(C, vertex_label(l)); R = union_find_find(C, vertex_label(r)); if (L != R) { union_find_union(C, L, R); E = edge_set_primary(E, true); } else { E = edge_set_primary(E, false); } result = graph_add_edge(result, E); pqueue_dequeue(Q); } while (!pqueue_is_empty(Q)) { E = edge_copy(pqueue_fst(Q)); pqueue_dequeue(Q); E = edge_set_primary(E, false); result = graph_add_edge(result, E); } Q = pqueue_destroy(Q); C = union_find_destroy(C); return result; }
int main() { unsigned int maxSize = 10; union_find_t uf = union_find_create(maxSize); bool exit = false; char *option = NULL; unsigned int u,v; printf("%u cantidad de nodos.\n",union_find_count(uf)); do { option = print_menu(); switch(*option) { case FIND: printf("\nPor favor ingrese el nodo a buscar: "); scanf("%u",&u); printf("\nEl representante es %u.\n",union_find_find(uf, u)); break; case UNION: printf("\nPor favor ingrese los conjuntos a unir: "); scanf("%u %u",&u,&v); union_find_union(uf, u, v); break; case CONNECT: printf("\nPor favor ingrese los nodos: "); scanf("%u %u",&u,&v); if(union_find_connected(uf, u, v)) printf("TRUE\n"); else printf("FALSE\n"); break; case EXIT: exit = true; break; } free(option); option = NULL; } while(!exit); uf = union_find_destroy(uf); }
graph_t kruskal(graph_t graph) { /* Computes a MST of the given graph. * * This function returns a copy of the input graph in which * only the edges of the MST are marked as primary. The * remaining edges are marked as secondary. * * The input graph does not change. * */ graph_t mst; union_find_t uf; pqueue_t pq; edge_t *edges; edge_t e; unsigned int left, right, n, m; /* Inicialización */ n = graph_vertices_count(graph); m = graph_edges_count(graph); mst = graph_empty(n); uf = union_find_create(n); pq = pqueue_empty(m); /* Llenar `pq` */ edges = graph_edges(graph); for (unsigned int j = 0; j < m; j++) { pqueue_enqueue(pq, edges[j]); } /* Ahora las aristas están en `pq` */ free(edges); edges = NULL; /* Principal */ while (!pqueue_is_empty(pq) && union_find_count(uf) > 1) { e = edge_copy(pqueue_fst(pq)); left = vertex_label(edge_left_vertex(e)); right = vertex_label(edge_right_vertex(e)); left = union_find_find(uf, left); right = union_find_find(uf, right); if (!union_find_connected(uf, left, right)) { e = edge_set_primary(e, true); union_find_union(uf, left, right); } else { e = edge_set_primary(e, false); } mst = graph_add_edge(mst, e); pqueue_dequeue(pq); } /* Agregar aristas restantes como secundarias */ while (!pqueue_is_empty(pq)) { e = edge_copy(pqueue_fst(pq)); e = edge_set_primary(e, false); mst = graph_add_edge(mst, e); pqueue_dequeue(pq); } /* Destroy */ uf = union_find_destroy(uf); pq = pqueue_destroy(pq); return (mst); }