You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
5.1 KiB
148 lines
5.1 KiB
/*
|
|
* Copyright(C) 1999-2020, 2023 National Technology & Engineering Solutions
|
|
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
|
|
* NTESS, the U.S. Government retains certain rights in this software.
|
|
*
|
|
* See packages/seacas/LICENSE for details
|
|
*/
|
|
|
|
#include "smalloc.h" // for smalloc
|
|
#include "structs.h" // for edgeslist, vtx_data
|
|
#include <stdio.h> // for NULL
|
|
|
|
static int bfsearch(struct vtx_data **graph, /* graph data structure */
|
|
int root, /* start vertex for DFS */
|
|
int *count, /* number of vertices in component */
|
|
int *mark, /* has vtx been seen? */
|
|
int *vtxlist, /* space for storing vtxs to search */
|
|
int comp_num /* current component number */
|
|
);
|
|
|
|
/* Breadth first search algorithm to find & mark connected components. */
|
|
int find_comps(struct vtx_data **graph, /* graph data structure */
|
|
int nvtxs, /* number of vertices in graph */
|
|
int *mark, /* space for nvtxs+1 ints */
|
|
int *vtxlist /* space for nvtxs ints */
|
|
)
|
|
{
|
|
int root; /* vertex to start the dfs */
|
|
int count; /* number of vertices seen so far */
|
|
int ncomps; /* number of components found */
|
|
int i; /* loop counter */
|
|
double drandom(void);
|
|
|
|
for (i = 1; i <= nvtxs; i++) {
|
|
mark[i] = -1;
|
|
}
|
|
count = 0;
|
|
ncomps = 0;
|
|
root = nvtxs * drandom() + 1;
|
|
|
|
bfsearch(graph, root, &count, mark, vtxlist, ncomps);
|
|
|
|
while (count != nvtxs) { /* Are there any remaining vertices? */
|
|
/* Find starting vtx for next BFS. */
|
|
root = nvtxs * drandom() + 1;
|
|
while (mark[root] >= 0) {
|
|
root++;
|
|
if (root > nvtxs) {
|
|
root = 1;
|
|
}
|
|
}
|
|
/* Add new edge to list needed for connectivity. */
|
|
ncomps++;
|
|
bfsearch(graph, root, &count, mark, vtxlist, ncomps);
|
|
}
|
|
return (ncomps + 1);
|
|
}
|
|
|
|
/* Breadth first search algorithm to find & mark connected components. */
|
|
/* Returns list of edges to connect them together. */
|
|
int find_edges(struct vtx_data **graph, /* graph data structure */
|
|
int nvtxs, /* number of vertices in graph */
|
|
int *mark, /* space for nvtxs+1 ints */
|
|
int *vtxlist, /* space for nvtxs ints */
|
|
struct edgeslist **edges /* list of edges connecting graph */
|
|
)
|
|
{
|
|
struct edgeslist *newedge; /* space to add new edge */
|
|
int root; /* vertex to start the dfs */
|
|
int last; /* last vertex seen in BFS */
|
|
int count; /* number of vertices seen so far */
|
|
int nadded; /* number of edges needed to be added */
|
|
int i; /* loop counter */
|
|
double drandom(void);
|
|
|
|
for (i = 1; i <= nvtxs; i++) {
|
|
mark[i] = -1;
|
|
}
|
|
count = 0;
|
|
nadded = 0;
|
|
*edges = NULL;
|
|
root = nvtxs * drandom() + 1;
|
|
|
|
last = bfsearch(graph, root, &count, mark, vtxlist, nadded);
|
|
|
|
while (count != nvtxs) { /* Are there any remaining vertices? */
|
|
/* Find starting vtx for next BFS. */
|
|
root = nvtxs * drandom() + 1;
|
|
while (mark[root] >= 0) {
|
|
root++;
|
|
if (root > nvtxs) {
|
|
root = 1;
|
|
}
|
|
}
|
|
/* Add new edge to list needed for connectivity. */
|
|
newedge = smalloc(sizeof(struct edgeslist));
|
|
newedge->next = *edges;
|
|
newedge->vtx1 = last;
|
|
newedge->vtx2 = root;
|
|
*edges = newedge;
|
|
nadded++;
|
|
last = bfsearch(graph, root, &count, mark, vtxlist, nadded);
|
|
}
|
|
return (nadded);
|
|
}
|
|
|
|
/* BFS to find connected component */
|
|
static int bfsearch(struct vtx_data **graph, /* graph data structure */
|
|
int root, /* start vertex for DFS */
|
|
int *count, /* number of vertices in component */
|
|
int *mark, /* has vtx been seen? */
|
|
int *vtxlist, /* space for storing vtxs to search */
|
|
int comp_num /* current component number */
|
|
)
|
|
{
|
|
int *iptr; /* loops through neighbor list */
|
|
int vtxbeg, vtxend; /* beginning and end of vertices in vtxlist */
|
|
int vtx; /* vertex being processed */
|
|
int neighbor; /* neighbor of vertex */
|
|
int i; /* loop counter */
|
|
|
|
vtxbeg = vtxend = 1;
|
|
mark[root] = comp_num;
|
|
vtxlist[0] = root;
|
|
|
|
/* Copy root's neighbors to vtxlist, incrementing count */
|
|
iptr = graph[root]->edges;
|
|
for (i = graph[root]->nedges - 1; i; i--) {
|
|
neighbor = *(++iptr);
|
|
vtxlist[vtxend++] = neighbor;
|
|
mark[neighbor] = comp_num;
|
|
}
|
|
|
|
while (vtxbeg < vtxend) {
|
|
vtx = vtxlist[vtxbeg++];
|
|
/* Loop through neighbors, copying to vtxlist if unmarked. */
|
|
iptr = graph[vtx]->edges;
|
|
for (i = graph[vtx]->nedges - 1; i; i--) {
|
|
neighbor = *(++iptr);
|
|
if (mark[neighbor] != comp_num) {
|
|
mark[neighbor] = comp_num;
|
|
vtxlist[vtxend++] = neighbor;
|
|
}
|
|
}
|
|
}
|
|
*count += vtxend;
|
|
return (vtxlist[vtxend - 1]);
|
|
}
|
|
|