From baee1ad457657c80fb959be4a2a66ed96830db54 Mon Sep 17 00:00:00 2001 From: Christian Schlittchen Date: Wed, 11 Apr 2001 17:28:07 +0000 Subject: [PATCH] =?UTF-8?q?-=20Einfach=20Graphroutinen,=20f=C3=BCr=20das?= =?UTF-8?q?=20Vorr=C3=BCcken.=20-=20Kleine=20Erweiterungen=20f=C3=BCr=20di?= =?UTF-8?q?e=20vsets.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/util/graph.c | 209 ++++++++++++++++++++++++++++++++++++++++ src/common/util/graph.h | 33 +++++++ src/common/util/vset.c | 39 +++++++- src/common/util/vset.h | 13 ++- 4 files changed, 286 insertions(+), 8 deletions(-) create mode 100644 src/common/util/graph.c create mode 100644 src/common/util/graph.h diff --git a/src/common/util/graph.c b/src/common/util/graph.c new file mode 100644 index 000000000..9c46bee31 --- /dev/null +++ b/src/common/util/graph.c @@ -0,0 +1,209 @@ +/* vi: set ts=2: + +-------------------+ Christian Schlittchen + | | Enno Rehling + | Eressea PBEM host | Katja Zedel + | (c) 1998 - 2001 | Henning Peters + | | Ingo Wilken + +-------------------+ Stefan Reich + + This program may not be used, modified or distributed + without prior permission by the authors of Eressea. + $Id: graph.c,v 1.1 2001/04/11 17:28:07 corwin Exp $ + */ + +/* This is a very simple graph library. It is not optimized in any + way, and relies heavily on the vset and stack routines. */ + +#include +#include "vset.h" +#include "graph.h" + +void +graph_init(graph *g) +{ + g->nodes = malloc(sizeof(vset)); + g->vertices = malloc(sizeof(vset)); + vset_init(g->nodes); + vset_init(g->vertices); +} + +void +graph_free(graph *g) +{ + vset_destroy(g->nodes); + vset_destroy(g->vertices); + free(g->nodes); + free(g->vertices); +} + +void +graph_add_node(graph *g, node *n) +{ + vset_add(g->nodes, n); +} + +void +graph_add_vertex(graph *g, vertex *v) +{ + vset_add(g->nodes, v); +} + +void +graph_remove_node(graph *g, node *n) +{ + int i; + + for(i=0; i != g->vertices->size; ++i) { + vertex *v = g->vertices->data[i]; + if(v->node1 == n || v->node2 == n) { + vset_erase(g->nodes, v); + i--; + } + } + vset_erase(g->nodes, n); +} + +node * +graph_find_node(graph *g, void *object) +{ + int i; + + for(i=0; i != g->nodes->size; ++i) { + node *node = g->nodes->data[i]; + if(node->object == object) { + return g->nodes->data[i]; + } + } + return NULL; +} + +/* The vset returned has to freed externally, else this will be a + memory leak. */ + +vset * +graph_neighbours(graph *g, node *n) +{ + int i; + vset *vs = malloc(sizeof(vset)); + vset_init(vs); + for(i=0; i != g->vertices->size; ++i) { + vertex *v = g->vertices->data[i]; + if(v->node1 == n && vset_count(vs, v->node2) == 0) { + vset_add(vs, v->node2); + } else if(v->node2 == n && vset_count(vs, v->node1) == 0) { + vset_add(vs, v->node1); + } + } + + return vs; +} + +void +graph_resetmarkers(graph *g) +{ + int i; + + for(i=0; i != g->nodes->size; ++i) { + node *node = g->nodes->data[i]; + node->marker = 0; + } + for(i=0; i != g->vertices->size; ++i) { + vertex *vertex = g->vertices->data[i]; + vertex->marker = 0; + } +} + +/* The vset returned has to freed externally, else this will be a + memory leak. */ + +vset * +graph_connected_nodes(graph *g, node *n) +{ + vset *vs = malloc(sizeof(vset)); + vset *s = malloc(sizeof(vset)); + + vset_init(vs); + vset_init(s); + graph_resetmarkers(g); + vset_add(vs, n); + n->marker = 1; + vset_add(s, n); + while(s->size > 0) { + node *n = vset_pop(s); + vset *vs_nb = graph_neighbours(g, n); + int i; + for(i=0; i != vs_nb->size; ++i) { + node *nb = vs_nb->data[i]; + if(nb->marker == 0) { + nb->marker == 1; + vset_add(vs, nb); + vset_add(s, nb); + } + } + vset_destroy(vs_nb); + free(vs_nb); + } + + vset_destroy(s); + free(s); + + return vs; +} + +/* The vset returned has to freed externally, else this will be a + memory leak. */ + +vset * +graph_disjunct_graphs(graph *g) +{ + vset *dg = malloc(sizeof(vset)); + vset *nodes = malloc(sizeof(vset)); + + vset_init(nodes); + vset_concat(nodes, g->nodes); + + while(nodes->size > 0) { + graph *gt = malloc(sizeof(graph)); + vset s; + int i; + node *start; + + graph_init(gt); + start = vset_pop(nodes); + graph_resetmarkers(g); + graph_add_node(gt, start); + start->marker = 1; + vset_init(&s); + vset_add(&s,start); + while(s.size > 0) { + vset *nbs = graph_neighbours(g,vset_pop(&s)); + for(i=0; i != nbs->size; ++i) { + node *nb = nbs->data[i]; + if(nb->marker == 0) { + nb->marker = 1; + graph_add_node(gt,nb); + vset_erase(nodes,nb); + vset_add(&s,nb); + } + } + vset_destroy(nbs); free(nbs); + } + + vset_destroy(&s); + + for(i=0;i != g->vertices->size; ++i) { + vertex *v = g->vertices->data[i]; + if(vset_count(g->nodes, v->node1)) { + graph_add_vertex(gt,v); + } + } + + vset_add(dg, gt); + } + + vset_destroy(nodes); + free(nodes); + + return dg; +} + diff --git a/src/common/util/graph.h b/src/common/util/graph.h new file mode 100644 index 000000000..6eed085f0 --- /dev/null +++ b/src/common/util/graph.h @@ -0,0 +1,33 @@ +/* vi: set ts=2: + +-------------------+ Christian Schlittchen + | | Enno Rehling + | Eressea PBEM host | Katja Zedel + | (c) 1998 - 2001 | Henning Peters + | | Ingo Wilken + +-------------------+ Stefan Reich + + This program may not be used, modified or distributed + without prior permission by the authors of Eressea. + $Id: graph.h,v 1.1 2001/04/11 17:28:07 corwin Exp $ + */ + +#ifndef GRAPH_H +#define GRAPH_H + +typedef struct { + int marker; + void *object; +} node; + +typedef struct { + int marker; + node *node1; + node *node2; +} vertex; + +typedef struct { + vset *nodes; + vset *vertices; +} graph; + +#endif diff --git a/src/common/util/vset.c b/src/common/util/vset.c index ab7c031c9..a567f89d3 100644 --- a/src/common/util/vset.c +++ b/src/common/util/vset.c @@ -1,6 +1,6 @@ /* vi: set ts=2: * - * $Id: vset.c,v 1.2 2001/01/26 16:19:41 enno Exp $ + * $Id: vset.c,v 1.3 2001/04/11 17:28:07 corwin Exp $ * Eressea PB(E)M host Copyright (C) 1998-2000 * Christian Schlittchen (corwin@amber.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de) @@ -41,7 +41,7 @@ vset_destroy(vset * s) int vset_erase(vset * s, void *item) { - unsigned int i; + size_t i; for (i = 0; i != s->size; ++i) if (s->data[i] == item) { @@ -51,10 +51,11 @@ vset_erase(vset * s, void *item) } return 0; } + unsigned int vset_add(vset * s, void *item) { - unsigned int i; + size_t i; if (!s->data) { s->size = 0; @@ -72,3 +73,35 @@ vset_add(vset * s, void *item) ++s->size; return s->size - 1; } + +void * +vset_pop(vset *s) +{ + if(s->size == 0) return NULL; + s->size--; + return data[s->size+1]; +} + +int +vset_count(vset *s, void *item) +{ + size_t i; + int c = 0; + + for(i = 0; i != s->size; ++i) { + if(s->data[i] == item) c++; + } + + return c; +} + +void +vset_concat(vset *to, vset *from) +{ + size_t i; + + for(i=0; i != from->size; ++i) { + vset_add(to, from->data[i]); + } +} + diff --git a/src/common/util/vset.h b/src/common/util/vset.h index 6fa4ff2dc..48ba2b7d1 100644 --- a/src/common/util/vset.h +++ b/src/common/util/vset.h @@ -1,6 +1,6 @@ /* vi: set ts=2: * - * $Id: vset.h,v 1.2 2001/01/26 16:19:41 enno Exp $ + * $Id: vset.h,v 1.3 2001/04/11 17:28:07 corwin Exp $ * Eressea PB(E)M host Copyright (C) 1998-2000 * Christian Schlittchen (corwin@amber.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de) @@ -21,9 +21,12 @@ struct vset { size_t size; size_t maxsize; }; -void vset_init(vset * s); -void vset_destroy(vset * s); -unsigned int vset_add(vset * s, void *); -int vset_erase(vset * s, void *); +extern void vset_init(vset * s); +extern void vset_destroy(vset * s); +extern unsigned int vset_add(vset * s, void *); +extern int vset_erase(vset * s, void *); +extern int vset_count(vset *s, void *item); +extern void *vset_pop(vset *s); +extern void vset_concat(vset *to, vset *from); #endif