- Einfach Graphroutinen, für das Vorrücken.

- Kleine Erweiterungen für die vsets.
This commit is contained in:
Christian Schlittchen 2001-04-11 17:28:07 +00:00
parent b5778f1cfd
commit baee1ad457
4 changed files with 286 additions and 8 deletions

209
src/common/util/graph.c Normal file
View File

@ -0,0 +1,209 @@
/* vi: set ts=2:
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea-pbem.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
| (c) 1998 - 2001 | Henning Peters <faroul@beyond.kn-bremen.de>
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
+-------------------+ Stefan Reich <reich@halbling.de>
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 <stdlib.h>
#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;
}

33
src/common/util/graph.h Normal file
View File

@ -0,0 +1,33 @@
/* vi: set ts=2:
+-------------------+ Christian Schlittchen <corwin@amber.kn-bremen.de>
| | Enno Rehling <enno@eressea-pbem.de>
| Eressea PBEM host | Katja Zedel <katze@felidae.kn-bremen.de>
| (c) 1998 - 2001 | Henning Peters <faroul@beyond.kn-bremen.de>
| | Ingo Wilken <Ingo.Wilken@informatik.uni-oldenburg.de>
+-------------------+ Stefan Reich <reich@halbling.de>
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

View File

@ -1,6 +1,6 @@
/* vi: set ts=2: /* 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 * Eressea PB(E)M host Copyright (C) 1998-2000
* Christian Schlittchen (corwin@amber.kn-bremen.de) * Christian Schlittchen (corwin@amber.kn-bremen.de)
* Katja Zedel (katze@felidae.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de)
@ -41,7 +41,7 @@ vset_destroy(vset * s)
int int
vset_erase(vset * s, void *item) vset_erase(vset * s, void *item)
{ {
unsigned int i; size_t i;
for (i = 0; i != s->size; ++i) for (i = 0; i != s->size; ++i)
if (s->data[i] == item) { if (s->data[i] == item) {
@ -51,10 +51,11 @@ vset_erase(vset * s, void *item)
} }
return 0; return 0;
} }
unsigned int unsigned int
vset_add(vset * s, void *item) vset_add(vset * s, void *item)
{ {
unsigned int i; size_t i;
if (!s->data) { if (!s->data) {
s->size = 0; s->size = 0;
@ -72,3 +73,35 @@ vset_add(vset * s, void *item)
++s->size; ++s->size;
return s->size - 1; 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]);
}
}

View File

@ -1,6 +1,6 @@
/* vi: set ts=2: /* 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 * Eressea PB(E)M host Copyright (C) 1998-2000
* Christian Schlittchen (corwin@amber.kn-bremen.de) * Christian Schlittchen (corwin@amber.kn-bremen.de)
* Katja Zedel (katze@felidae.kn-bremen.de) * Katja Zedel (katze@felidae.kn-bremen.de)
@ -21,9 +21,12 @@ struct vset {
size_t size; size_t size;
size_t maxsize; size_t maxsize;
}; };
void vset_init(vset * s); extern void vset_init(vset * s);
void vset_destroy(vset * s); extern void vset_destroy(vset * s);
unsigned int vset_add(vset * s, void *); extern unsigned int vset_add(vset * s, void *);
int vset_erase(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 #endif