[GRASS-SVN] r42281 - in grass/trunk: include include/Make
include/vect lib lib/btree2 lib/segment lib/vector/Vlib
lib/vector/diglib raster/r.watershed/ram
svn_grass at osgeo.org
svn_grass at osgeo.org
Tue May 18 05:42:15 EDT 2010
Author: mmetz
Date: 2010-05-18 05:42:14 -0400 (Tue, 18 May 2010)
New Revision: 42281
Added:
grass/trunk/include/rbtree.h
grass/trunk/lib/btree2/
grass/trunk/lib/btree2/Makefile
grass/trunk/lib/btree2/README
grass/trunk/lib/btree2/rbtree.c
Removed:
grass/trunk/include/vect/rbtree.h
grass/trunk/lib/segment/rbtree.c
grass/trunk/lib/segment/rbtree.h
grass/trunk/lib/vector/diglib/rbtree.c
grass/trunk/raster/r.watershed/ram/rbtree.c
grass/trunk/raster/r.watershed/ram/rbtree.h
Modified:
grass/trunk/include/Make/Grass.make
grass/trunk/include/vect/dig_structs.h
grass/trunk/lib/Makefile
grass/trunk/lib/segment/Makefile
grass/trunk/lib/segment/pagein.c
grass/trunk/lib/segment/release.c
grass/trunk/lib/segment/setup.c
grass/trunk/lib/vector/Vlib/break_polygons.c
grass/trunk/lib/vector/Vlib/snap.c
grass/trunk/raster/r.watershed/ram/Makefile
grass/trunk/raster/r.watershed/ram/do_flatarea.c
Log:
add balanced search tree to lib, update Vlib and segment
Modified: grass/trunk/include/Make/Grass.make
===================================================================
--- grass/trunk/include/Make/Grass.make 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/include/Make/Grass.make 2010-05-18 09:42:14 UTC (rev 42281)
@@ -112,6 +112,7 @@
BASIC:basic \
BITMAP:bitmap \
BTREE:btree \
+ BTREE2:btree2 \
CAIRODRIVER:cairodriver \
CDHC:cdhc \
CCMATH:ccmath \
@@ -213,13 +214,13 @@
RLIDEPS = $(RASTERLIB) $(GISLIB) $(MATHLIB)
ROWIODEPS = $(GISLIB)
RTREEDEPS = $(MATHLIB)
-SEGMENTDEPS = $(GISLIB)
+SEGMENTDEPS = $(GISLIB) $(BTREE2LIB)
#SIMDEPS = $(VECTLIB) $(BITMAPLIB) $(GMATHLIB) $(LINKMLIB) $(SITESLIB) $(DBMILIB) $(GISLIB)
SITESDEPS = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(DATETIMELIB)
STATSDEPS = $(RASTERLIB) $(GISLIB) $(MATHLIB) # NB: doesn't use libgis directly
SYMBDEPS = $(GISLIB) $(MATHLIB)
TRANSDEPS = $(MATHLIB)
-VECTORDEPS = $(DBMILIB) $(GRAPHLIB) $(DIG2LIB) $(LINKMLIB) $(RTREELIB) $(GISLIB) $(GEOSLIBS) $(GDALLIBS) $(MATHLIB)
+VECTORDEPS = $(DBMILIB) $(GRAPHLIB) $(DIG2LIB) $(LINKMLIB) $(RTREELIB) $(GISLIB) $(GEOSLIBS) $(GDALLIBS) $(MATHLIB) $(BTREE2LIB)
VEDITDEPS = $(VECTORLIB) $(DBMILIB) $(GISLIB) $(MATHLIB)
NETADEPS = $(VECTORDEP) $(DBMIDEP) $(GISDEP)
@@ -276,7 +277,7 @@
DBMILIB = $(DBMICLIENTLIB) $(DBMIBASELIB) $(DBMIEXTRALIB)
GEOMLIB = $(OPTRILIB) $(SOSLIB) $(LIALIB) $(BASICLIB)
-VECTLIB = $(VECTORLIB) $(DIG2LIB) $(GRAPHLIB) $(RTREELIB) $(LINKMLIB) $(DBMILIB)
+VECTLIB = $(VECTORLIB) $(DIG2LIB) $(GRAPHLIB) $(RTREELIB) $(LINKMLIB) $(DBMILIB) $(BTREE2LIB)
DBMIDEP = $(DBMICLIENTDEP) $(DBMIBASEDEP)
GEOMDEP = $(OPTRIDEP) $(SOSDEP) $(LIADEP) $(BASICDEP)
Added: grass/trunk/include/rbtree.h
===================================================================
--- grass/trunk/include/rbtree.h (rev 0)
+++ grass/trunk/include/rbtree.h 2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,112 @@
+/*************************************************************
+ * USAGE *
+ *************************************************************
+ *
+ * NOTE: duplicates are not supported
+ *
+ * custom compare function
+ * extern int my_compare_fn(const void *, const void *);
+ * int my_compare_fn(const void *a, const void *b) {
+ * if ((mydatastruct *) a < (mydatastruct *) b)
+ * return -1;
+ * else if ((mydatastruct *) a > (mydatastruct *) b)
+ * return 1;
+ * else if ((mydatastruct *) a == (mydatastruct *) b)
+ * return 0;
+ * }
+ *
+ * create and initialize tree:
+ * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
+ *
+ * insert items to tree:
+ * struct mydatastruct data = <some data>;
+ * if (rbtree_insert(mytree, &data) == 0)
+ * G_warning("could not insert data");
+ *
+ * find item in tree:
+ * struct mydatastruct data = <some data>;
+ * if (rbtree_find(mytree, &data) == 0)
+ * G_message("data not found");
+ *
+ * delete item from tree:
+ * struct mydatastruct data = <some data>;
+ * if (rbtree_remove(mytree, &data) == 0)
+ * G_warning("could not find data in tree");
+ *
+ * traverse tree (get all items in tree in ascending order):
+ * struct RB_TRAV trav;
+ * rbtree_init_trav(&trav, tree);
+ * while ((data = rbtree_traverse(&trav)) != NULL) {
+ * if (my_compare_fn(data, threshold_data) == 0) break;
+ * <do something with data>;
+ * }
+ *
+ * get a selection of items: all data > data1 and < data2
+ * start in tree where data is last smaller or first larger compared to data1
+ * struct RB_TRAV trav;
+ * rbtree_init_trav(&trav, tree);
+ * data = rbtree_traverse_start(&trav, &data1);
+ * <do something with data>;
+ * while ((data = rbtree_traverse(&trav)) != NULL) {
+ * if (data > data2) break;
+ * <do something with data>;
+ * }
+ *
+ * destroy tree:
+ * rbtree_destroy(mytree);
+ *
+ * debug the whole tree with
+ * rbtree_debug(mytree, mytree->root);
+ *
+ *************************************************************/
+
+#include <stddef.h>
+
+/* maximum RB Tree height */
+#define RBTREE_MAX_HEIGHT 64 /* should be more than enough */
+
+/* routine to compare data items
+ * return -1 if rb_a < rb_b
+ * return 0 if rb_a == rb_b
+ * return 1 if rb_a > rb_b
+ */
+typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
+
+struct RB_NODE
+{
+ unsigned char red; /* 0 = black, 1 = red */
+ void *data; /* any kind of data */
+ struct RB_NODE *link[2]; /* link to children: link[0] for smaller, link[1] for larger */
+};
+
+struct RB_TREE
+{
+ struct RB_NODE *root; /* root node */
+ size_t datasize; /* item size */
+ size_t count; /* number of items in tree. */
+ rb_compare_fn *rb_compare; /* function to compare data */
+};
+
+struct RB_TRAV
+{
+ struct RB_TREE *tree; /* tree being traversed */
+ struct RB_NODE *curr_node; /* current node */
+ struct RB_NODE *up[RBTREE_MAX_HEIGHT]; /* stack of parent nodes */
+ int top; /* index for stack */
+ int first; /* little helper flag */
+};
+
+/* tree functions */
+struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
+void rbtree_destroy(struct RB_TREE *);
+int rbtree_insert(struct RB_TREE *, void *);
+int rbtree_remove(struct RB_TREE *, const void *);
+void *rbtree_find(struct RB_TREE *, const void *);
+
+/* tree traversal functions */
+int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
+void* rbtree_traverse(struct RB_TRAV *);
+void *rbtree_traverse_start(struct RB_TRAV *, const void *);
+
+/* debug tree from given node downwards */
+int rbtree_debug(struct RB_TREE *, struct RB_NODE *);
Modified: grass/trunk/include/vect/dig_structs.h
===================================================================
--- grass/trunk/include/vect/dig_structs.h 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/include/vect/dig_structs.h 2010-05-18 09:42:14 UTC (rev 42281)
@@ -20,7 +20,7 @@
#include <grass/dgl.h>
#include <grass/shapefil.h>
-#include <grass/btree.h>
+#include <grass/rbtree.h>
#include <grass/rtree.h>
#ifdef HAVE_OGR
@@ -31,7 +31,7 @@
3.10 changes plus_t to ints.
This assumes that any reasonable machine will use 4 bytes to
- store an int. The mapdev code is not guaranteed to work if
+ store an int. The diglib code is not guaranteed to work if
plus_t is changed to a type that is larger than an int.
*/
typedef int plus_t;
Deleted: grass/trunk/include/vect/rbtree.h
===================================================================
--- grass/trunk/include/vect/rbtree.h 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/include/vect/rbtree.h 2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,112 +0,0 @@
-/*************************************************************
- * USAGE *
- *************************************************************
- *
- * NOTE: duplicates are not supported
- *
- * custom compare function
- * extern int my_compare_fn(const void *, const void *);
- * int my_compare_fn(const void *a, const void *b) {
- * if ((mydatastruct *) a < (mydatastruct *) b)
- * return -1;
- * else if ((mydatastruct *) a > (mydatastruct *) b)
- * return 1;
- * else if ((mydatastruct *) a == (mydatastruct *) b)
- * return 0;
- * }
- *
- * create and initialize tree:
- * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
- *
- * insert items to tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_insert(mytree, &data) == 0)
- * G_warning("could not insert data");
- *
- * find item in tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_find(mytree, &data) == 0)
- * G_message("data not found");
- *
- * delete item from tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_remove(mytree, &data) == 0)
- * G_warning("could not find data in tree");
- *
- * traverse tree (get all items in tree in ascending order):
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- * if (my_compare_fn(data, threshold_data) == 0) break;
- * <do something with data>;
- * }
- *
- * get a selection of items: all data > data1 and < data2
- * start in tree where data is last smaller or first larger compared to data1
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * data = rbtree_traverse_start(&trav, &data1);
- * <do something with data>;
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- * if (data > data2) break;
- * <do something with data>;
- * }
- *
- * destroy tree:
- * rbtree_destroy(mytree);
- *
- * debug the whole tree with
- * rbtree_debug(mytree, mytree->root);
- *
- *************************************************************/
-
-#include <stddef.h>
-
-/* maximum RB Tree height */
-#define RBTREE_MAX_HEIGHT 64 /* should be more than enough */
-
-/* routine to compare data items
- * return -1 if rb_a < rb_b
- * return 0 if rb_a == rb_b
- * return 1 if rb_a > rb_b
- */
-typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
-
-struct RB_NODE
-{
- unsigned char red; /* 0 = black, 1 = red */
- void *data; /* any kind of data */
- struct RB_NODE *link[2]; /* link to children: link[0] for smaller, link[1] for larger */
-};
-
-struct RB_TREE
-{
- struct RB_NODE *root; /* root node */
- size_t datasize; /* item size */
- size_t count; /* number of items in tree. */
- rb_compare_fn *rb_compare; /* function to compare data */
-};
-
-struct RB_TRAV
-{
- struct RB_TREE *tree; /* tree being traversed */
- struct RB_NODE *curr_node; /* current node */
- struct RB_NODE *up[RBTREE_MAX_HEIGHT]; /* stack of parent nodes */
- int top; /* index for stack */
- int first; /* little helper flag */
-};
-
-/* tree functions */
-struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
-void rbtree_destroy(struct RB_TREE *);
-int rbtree_insert(struct RB_TREE *, void *);
-int rbtree_remove(struct RB_TREE *, const void *);
-void *rbtree_find(struct RB_TREE *, const void *);
-
-/* tree traversal functions */
-int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
-void* rbtree_traverse(struct RB_TRAV *);
-void *rbtree_traverse_start(struct RB_TRAV *, const void *);
-
-/* debug tree from given node downwards */
-int rbtree_debug(struct RB_TREE *, struct RB_NODE *);
Modified: grass/trunk/lib/Makefile
===================================================================
--- grass/trunk/lib/Makefile 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/Makefile 2010-05-18 09:42:14 UTC (rev 42281)
@@ -17,6 +17,7 @@
cairodriver \
bitmap \
btree \
+ btree2 \
display \
db \
fonts \
Added: grass/trunk/lib/btree2/Makefile
===================================================================
--- grass/trunk/lib/btree2/Makefile (rev 0)
+++ grass/trunk/lib/btree2/Makefile 2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,11 @@
+MODULE_TOPDIR = ../..
+
+include $(MODULE_TOPDIR)/include/Make/Vars.make
+
+MOD_OBJS := $(filter-out try.o,$(AUTO_OBJS))
+
+LIB = BTREE2
+
+include $(MODULE_TOPDIR)/include/Make/Lib.make
+
+default: lib
Added: grass/trunk/lib/btree2/README
===================================================================
--- grass/trunk/lib/btree2/README (rev 0)
+++ grass/trunk/lib/btree2/README 2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,75 @@
+
+#include <grass/rbtree.h>
+
+and link to BTREE2LIB
+
+to make use of this binary balanced (Red-Black) search tree
+
+NOTE: duplicates are not supported
+
+
+USAGE
+=====
+
+see also grass/rbtree.h for instructions on how to use it
+
+/* custom compare function */
+extern int my_compare_fn(const void *, const void *);
+int my_compare_fn(const void *a, const void *b)
+{
+ if ((mydatastruct *) a < (mydatastruct *) b)
+ return -1;
+ else if ((mydatastruct *) a > (mydatastruct *) b)
+ return 1;
+ else if ((mydatastruct *) a == (mydatastruct *) b)
+ return 0;
+}
+
+/* create and initialize tree: */
+struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
+
+/* insert items to tree: */
+ struct mydatastruct data = <some data>;
+
+ if (rbtree_insert(mytree, &data) == 0)
+ G_warning("could not insert data");
+
+/* find item in tree: */
+ struct mydatastruct data = <some data>;
+
+ if (rbtree_find(mytree, &data) == 0)
+ G_message("data not found");
+
+/* delete item from tree: */
+ struct mydatastruct data = <some data>;
+
+ if (rbtree_remove(mytree, &data) == 0)
+ G_warning("could not find data in tree");
+
+/* traverse tree (get all items in tree in ascending order): */
+ struct RB_TRAV trav;
+
+ rbtree_init_trav(&trav, tree);
+ while ((data = rbtree_traverse(&trav)) != NULL) {
+ if (my_compare_fn(data, threshold_data) == 0) break;
+ /* do something with data */
+ }
+
+/* get a selection of items: all data > data1 and < data2
+ * start in tree where data is last smaller or first larger compared to data1 */
+ struct RB_TRAV trav;
+
+ rbtree_init_trav(&trav, tree);
+ data = rbtree_traverse_start(&trav, &data1);
+ /* do something with data */
+ while ((data = rbtree_traverse(&trav)) != NULL) {
+ if (data > data2) break;
+ /* do something with data */
+ }
+
+/* destroy tree: */
+ rbtree_destroy(mytree);
+
+/* debug the whole tree with */
+ rbtree_debug(mytree, mytree->root);
+
Added: grass/trunk/lib/btree2/rbtree.c
===================================================================
--- grass/trunk/lib/btree2/rbtree.c (rev 0)
+++ grass/trunk/lib/btree2/rbtree.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -0,0 +1,534 @@
+/*!
+ * \file rbtree.c
+ *
+ * \brief binary search tree
+ *
+ * Generic balanced binary search tree (Red Black Tree) implementation
+ *
+ * (C) 2009 by the GRASS Development Team
+ *
+ * This program is free software under the GNU General Public License
+ * (>=v2). Read the file COPYING that comes with GRASS for details.
+ *
+ * \author Original author Julienne Walker 2003, 2008
+ * GRASS implementation Markus Metz, 2009
+ */
+
+/* balanced binary search tree implementation
+ *
+ * this one is a Red Black Tree, no parent pointers, no threads
+ * The core code comes from Julienne Walker's tutorials on binary search trees
+ * original license: public domain
+ * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
+ * some ideas come from libavl (GPL >= 2)
+ *
+ * Red Black Trees are used to maintain a data structure with
+ * search, insertion and deletion in O(log N) time
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include <grass/rbtree.h>
+
+/* internal functions */
+void rbtree_destroy2(struct RB_NODE *);
+struct RB_NODE *rbtree_single(struct RB_NODE *, int);
+struct RB_NODE *rbtree_double(struct RB_NODE *, int);
+void *rbtree_first(struct RB_TRAV *);
+void *rbtree_next(struct RB_TRAV *);
+struct RB_NODE *rbtree_make_node(size_t, void *);
+int is_red(struct RB_NODE *);
+
+
+/* create new tree and initialize
+ * returns pointer to new tree, NULL for memory allocation error
+ */
+struct RB_TREE *rbtree_create(rb_compare_fn *compare, size_t rb_datasize)
+{
+ struct RB_TREE *tree = G_malloc(sizeof(*tree));
+
+ if (tree == NULL) {
+ G_warning("RB tree: Out of memory!");
+ return NULL;
+ }
+
+ assert(compare);
+
+ tree->datasize = rb_datasize;
+ tree->rb_compare = compare;
+ tree->count = 0;
+ tree->root = NULL;
+
+ return tree;
+}
+
+/* add an item to a tree
+ * non-recursive top-down insertion
+ * the algorithm does not allow duplicates and also does not warn about a duplicate
+ * returns 1 on success, 0 on failure
+ */
+int rbtree_insert(struct RB_TREE *tree, void *data)
+{
+ assert(tree && data);
+
+ if (tree->root == NULL) {
+ /* create a new root node for tree */
+ tree->root = rbtree_make_node(tree->datasize, data);
+ if (tree->root == NULL)
+ return 0;
+ }
+ else {
+ struct RB_NODE head = { 0 }; /* False tree root */
+ struct RB_NODE *g, *t; /* Grandparent & parent */
+ struct RB_NODE *p, *q; /* Iterator & parent */
+ int dir = 0, last = 0;
+
+ /* Set up helpers */
+ t = &head;
+ g = p = NULL;
+ q = t->link[1] = tree->root;
+
+ /* Search down the tree */
+ for (;;) {
+ if (q == NULL) {
+ /* Insert new node at the bottom */
+ p->link[dir] = q = rbtree_make_node(tree->datasize, data);
+ if (q == NULL)
+ return 0;
+ }
+ else if (is_red(q->link[0]) && is_red(q->link[1])) {
+ /* Color flip */
+ q->red = 1;
+ q->link[0]->red = 0;
+ q->link[1]->red = 0;
+ }
+
+ /* Fix red violation */
+ if (is_red(q) && is_red(p)) {
+ int dir2 = t->link[1] == g;
+
+ if (q == p->link[last])
+ t->link[dir2] = rbtree_single(g, !last);
+ else
+ t->link[dir2] = rbtree_double(g, !last);
+ }
+
+ last = dir;
+ dir = tree->rb_compare(q->data, data);
+
+ /* Stop if found. This check also disallows duplicates in the tree */
+ if (dir == 0)
+ break;
+
+ dir = dir < 0;
+
+ /* Move the helpers down */
+ if (g != NULL)
+ t = g;
+
+ g = p, p = q;
+ q = q->link[dir];
+ }
+
+ /* Update root */
+ tree->root = head.link[1];
+ }
+
+ /* Make root black */
+ tree->root->red = 0;
+
+ tree->count++;
+
+ return 1;
+}
+
+/* remove an item from a tree that matches given data
+ * non-recursive top-down removal
+ * returns 1 on successful removal
+ * returns 0 if data item was not found
+ */
+int rbtree_remove(struct RB_TREE *tree, const void *data)
+{
+ struct RB_NODE head = { 0 }; /* False tree root */
+ struct RB_NODE *q, *p, *g; /* Helpers */
+ struct RB_NODE *f = NULL; /* Found item */
+ int dir = 1, removed = 0;
+
+ assert(tree && data);
+
+ if (tree->root == NULL) {
+ return 0; /* empty tree, nothing to remove */
+ }
+
+ /* Set up helpers */
+ q = &head;
+ g = p = NULL;
+ q->link[1] = tree->root;
+
+ /* Search and push a red down */
+ while (q->link[dir] != NULL) {
+ int last = dir;
+
+ /* Update helpers */
+ g = p, p = q;
+ q = q->link[dir];
+ dir = tree->rb_compare(q->data, data);
+
+ /* Save found node */
+ if (dir == 0)
+ f = q;
+
+ dir = dir < 0;
+
+ /* Push the red node down */
+ if (!is_red(q) && !is_red(q->link[dir])) {
+ if (is_red(q->link[!dir]))
+ p = p->link[last] = rbtree_single(q, dir);
+ else if (!is_red(q->link[!dir])) {
+ struct RB_NODE *s = p->link[!last];
+
+ if (s != NULL) {
+ if (!is_red(s->link[!last]) && !is_red(s->link[last])) {
+ /* Color flip */
+ p->red = 0;
+ s->red = 1;
+ q->red = 1;
+ }
+ else {
+ int dir2 = g->link[1] == p;
+
+ if (is_red(s->link[last]))
+ g->link[dir2] = rbtree_double(p, last);
+ else if (is_red(s->link[!last]))
+ g->link[dir2] = rbtree_single(p, last);
+
+ /* Ensure correct coloring */
+ q->red = g->link[dir2]->red = 1;
+ g->link[dir2]->link[0]->red = 0;
+ g->link[dir2]->link[1]->red = 0;
+ }
+ }
+ }
+ }
+ }
+
+ /* Replace and remove if found */
+ if (f != NULL) {
+ G_free(f->data);
+ f->data = q->data;
+ p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
+ G_free(q);
+ tree->count--;
+ removed = 1;
+ }
+ else
+ G_debug(2, "RB tree: data not found in search tree");
+
+ /* Update root and make it black */
+ tree->root = head.link[1];
+ if (tree->root != NULL)
+ tree->root->red = 0;
+
+ return removed;
+}
+
+/* find data item in tree
+ * returns pointer to data item if found else NULL
+ */
+void *rbtree_find(struct RB_TREE *tree, const void *data)
+{
+ struct RB_NODE *curr_node = tree->root;
+ int cmp;
+
+ assert(tree && data);
+
+ while (curr_node != NULL) {
+ cmp = tree->rb_compare(curr_node->data, data);
+ if (cmp == 0)
+ return curr_node->data; /* found */
+
+ curr_node = curr_node->link[cmp < 0];
+ }
+ return NULL;
+}
+
+/* initialize tree traversal
+ * (re-)sets trav structure
+ * returns 0
+ */
+int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
+{
+ assert(trav && tree);
+
+ trav->tree = tree;
+ trav->curr_node = tree->root;
+ trav->first = 1;
+ trav->top = 0;
+
+ return 0;
+}
+
+/* traverse the tree in ascending order
+ * useful to get all items in the tree non-recursively
+ * struct RB_TRAV *trav needs to be initialized first
+ * returns pointer to data, NULL when finished
+ */
+void *rbtree_traverse(struct RB_TRAV *trav)
+{
+ assert(trav);
+
+ if (trav->curr_node == NULL) {
+ if (trav->first)
+ G_debug(1, "RB tree: empty tree");
+ else
+ G_debug(1, "RB tree: finished traversing");
+
+ return NULL;
+ }
+
+ if (!trav->first)
+ return rbtree_next(trav);
+ else {
+ trav->first = 0;
+ return rbtree_first(trav);
+ }
+}
+
+/* find start point to traverse the tree in ascending order
+ * useful to get a selection of items in the tree
+ * magnitudes faster than traversing the whole tree
+ * may return first item that's smaller or first item that's larger
+ * struct RB_TRAV *trav needs to be initialized first
+ * returns pointer to data, NULL when finished
+ */
+void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
+{
+ int dir = 0;
+
+ assert(trav && data);
+
+ if (trav->curr_node == NULL) {
+ if (trav->first)
+ G_warning("RB tree: empty tree");
+ else
+ G_warning("RB tree: finished traversing");
+
+ return NULL;
+ }
+
+ if (!trav->first)
+ return rbtree_next(trav);
+
+ /* else first time, get start node */
+
+ trav->first = 0;
+ trav->top = 0;
+
+ while (trav->curr_node != NULL) {
+ dir = trav->tree->rb_compare(trav->curr_node->data, data);
+ /* exact match, great! */
+ if (dir == 0)
+ return trav->curr_node->data;
+ else {
+ dir = dir < 0;
+ /* end of branch, also reached if
+ * smallest item is larger than search template or
+ * largest item is smaller than search template */
+ if (trav->curr_node->link[dir] == NULL)
+ return trav->curr_node->data;
+
+ trav->up[trav->top++] = trav->curr_node;
+ trav->curr_node = trav->curr_node->link[dir];
+ }
+ }
+
+ return NULL; /* should not happen */
+}
+
+/* two functions needed to fully traverse the tree: initialize and continue
+ * useful to get all items in the tree non-recursively
+ * this one here uses a stack
+ * parent pointers or threads would also be possible
+ * but these would need to be added to RB_NODE
+ * -> more memory needed for standard operations
+ */
+
+/* start traversing the tree
+ * returns pointer to smallest data item
+ */
+void *rbtree_first(struct RB_TRAV *trav)
+{
+ /* get smallest item */
+ while (trav->curr_node->link[0] != NULL) {
+ trav->up[trav->top++] = trav->curr_node;
+ trav->curr_node = trav->curr_node->link[0];
+ }
+
+ return trav->curr_node->data; /* return smallest item */
+}
+
+/* continue traversing the tree in ascending order
+ * returns pointer to data item, NULL when finished
+ */
+void *rbtree_next(struct RB_TRAV *trav)
+{
+ if (trav->curr_node->link[1] != NULL) {
+ /* something on the right side: larger item */
+ trav->up[trav->top++] = trav->curr_node;
+ trav->curr_node = trav->curr_node->link[1];
+
+ /* go down, find smallest item in this branch */
+ while (trav->curr_node->link[0] != NULL) {
+ trav->up[trav->top++] = trav->curr_node;
+ trav->curr_node = trav->curr_node->link[0];
+ }
+ }
+ else {
+ /* at smallest item in this branch, go back up */
+ struct RB_NODE *last;
+
+ do {
+ if (trav->top == 0) {
+ trav->curr_node = NULL;
+ break;
+ }
+ last = trav->curr_node;
+ trav->curr_node = trav->up[--trav->top];
+ } while (last == trav->curr_node->link[1]);
+ }
+
+ if (trav->curr_node != NULL) {
+ return trav->curr_node->data;
+ }
+ else
+ return NULL; /* finished traversing */
+}
+
+/* destroy the tree */
+void rbtree_destroy(struct RB_TREE *tree)
+{
+ rbtree_destroy2(tree->root);
+ G_free(tree);
+}
+
+void rbtree_destroy2(struct RB_NODE *root)
+{
+ if (root != NULL) {
+ rbtree_destroy2(root->link[0]);
+ rbtree_destroy2(root->link[1]);
+ G_free(root->data);
+ G_free(root);
+ }
+}
+
+/* used for debugging: check for errors in tree structure */
+int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
+{
+ int lh, rh;
+
+ if (root == NULL)
+ return 1;
+ else {
+ struct RB_NODE *ln = root->link[0];
+ struct RB_NODE *rn = root->link[1];
+ int lcmp = 0, rcmp = 0;
+
+ /* Consecutive red links */
+ if (is_red(root)) {
+ if (is_red(ln) || is_red(rn)) {
+ G_warning("Red Black Tree debugging: Red violation");
+ return 0;
+ }
+ }
+
+ lh = rbtree_debug(tree, ln);
+ rh = rbtree_debug(tree, rn);
+
+ if (ln) {
+ lcmp = tree->rb_compare(ln->data, root->data);
+ }
+
+ if (rn) {
+ rcmp = tree->rb_compare(rn->data, root->data);
+ }
+
+ /* Invalid binary search tree:
+ * left node >= parent or right node <= parent */
+ if ((ln != NULL && lcmp > -1)
+ || (rn != NULL && rcmp < 1)) {
+ G_warning("Red Black Tree debugging: Binary tree violation");
+ return 0;
+ }
+
+ /* Black height mismatch */
+ if (lh != 0 && rh != 0 && lh != rh) {
+ G_warning("Red Black Tree debugging: Black violation");
+ return 0;
+ }
+
+ /* Only count black links */
+ if (lh != 0 && rh != 0)
+ return is_red(root) ? lh : lh + 1;
+ else
+ return 0;
+ }
+}
+
+/*******************************************************
+ * *
+ * internal functions for Red Black Tree maintenance *
+ * *
+ *******************************************************/
+
+/* add a new node to the tree */
+struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
+{
+ struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
+
+ if (new_node == NULL)
+ G_fatal_error("RB Search Tree: Out of memory!");
+
+ new_node->data = G_malloc(datasize);
+ if (new_node->data == NULL)
+ G_fatal_error("RB Search Tree: Out of memory!");
+
+ memcpy(new_node->data, data, datasize);
+ new_node->red = 1; /* 1 is red, 0 is black */
+ new_node->link[0] = NULL;
+ new_node->link[1] = NULL;
+
+ return new_node;
+}
+
+/* check for red violation */
+int is_red(struct RB_NODE *root)
+{
+ if (root)
+ return root->red == 1;
+
+ return 0;
+}
+
+/* single rotation */
+struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
+{
+ struct RB_NODE *newroot = root->link[!dir];
+
+ root->link[!dir] = newroot->link[dir];
+ newroot->link[dir] = root;
+
+ root->red = 1;
+ newroot->red = 0;
+
+ return newroot;
+}
+
+/* double rotation */
+struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
+{
+ root->link[!dir] = rbtree_single(root->link[!dir], !dir);
+ return rbtree_single(root, dir);
+}
Modified: grass/trunk/lib/segment/Makefile
===================================================================
--- grass/trunk/lib/segment/Makefile 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/Makefile 2010-05-18 09:42:14 UTC (rev 42281)
@@ -3,6 +3,8 @@
LIB = SEGMENT
+LIBES = $(BTREE2LIB)
+
include $(MODULE_TOPDIR)/include/Make/Lib.make
include $(MODULE_TOPDIR)/include/Make/Doxygen.make
Modified: grass/trunk/lib/segment/pagein.c
===================================================================
--- grass/trunk/lib/segment/pagein.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/pagein.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -17,7 +17,7 @@
#include <string.h>
#include <errno.h>
#include <grass/segment.h>
-#include "rbtree.h"
+#include <grass/rbtree.h>
/**
Deleted: grass/trunk/lib/segment/rbtree.c
===================================================================
--- grass/trunk/lib/segment/rbtree.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/rbtree.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,535 +0,0 @@
-/*!
- * \file rbtree.c
- *
- * \brief binary search tree
- *
- * Generic balanced binary search tree (Red Black Tree) implementation
- *
- * (C) 2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2). Read the file COPYING that comes with GRASS for details.
- *
- * \author Original author Julienne Walker 2003, 2008
- * GRASS implementation Markus Metz, 2009
- */
-
-/* balanced binary search tree implementation
- *
- * this one is a Red Black Tree, the bare version, no parent pointers, no threads
- * The core code comes from Julienne Walker's tutorials on binary search trees
- * original license: public domain
- * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
- * some ideas come from libavl (GPL >= 2)
- * I could have used some off-the-shelf solution, but that's boring
- *
- * Red Black Trees are used to maintain a data structure with
- * search, insertion and deletion in O(log N) time
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include "rbtree.h"
-
-/* internal functions */
-void rbtree_destroy2(struct RB_NODE *);
-struct RB_NODE *rbtree_single(struct RB_NODE *, int);
-struct RB_NODE *rbtree_double(struct RB_NODE *, int);
-void *rbtree_first(struct RB_TRAV *);
-void *rbtree_next(struct RB_TRAV *);
-struct RB_NODE *rbtree_make_node(size_t, void *);
-int is_red(struct RB_NODE *);
-
-
-/* create new tree and initialize
- * returns pointer to new tree, NULL for memory allocation error
- */
-struct RB_TREE *rbtree_create(rb_compare_fn * compare, size_t rb_datasize)
-{
- struct RB_TREE *tree = G_malloc(sizeof(*tree));
-
- if (tree == NULL) {
- G_warning("RB tree: Out of memory!");
- return NULL;
- }
-
- assert(compare);
-
- tree->datasize = rb_datasize;
- tree->rb_compare = compare;
- tree->count = 0;
- tree->root = NULL;
-
- return tree;
-}
-
-/* add an item to a tree
- * non-recursive top-down insertion
- * the algorithm does not allow duplicates and also does not warn about a duplicate
- * returns 1 on success, 0 on failure
- */
-int rbtree_insert(struct RB_TREE *tree, void *data)
-{
- assert(tree && data);
-
- if (tree->root == NULL) {
- /* create a new root node for tree */
- tree->root = rbtree_make_node(tree->datasize, data);
- if (tree->root == NULL)
- return 0;
- }
- else {
- struct RB_NODE head = { 0 }; /* False tree root */
- struct RB_NODE *g, *t; /* Grandparent & parent */
- struct RB_NODE *p, *q; /* Iterator & parent */
- int dir = 0, last = 0;
-
- /* Set up helpers */
- t = &head;
- g = p = NULL;
- q = t->link[1] = tree->root;
-
- /* Search down the tree */
- for (;;) {
- if (q == NULL) {
- /* Insert new node at the bottom */
- p->link[dir] = q = rbtree_make_node(tree->datasize, data);
- if (q == NULL)
- return 0;
- }
- else if (is_red(q->link[0]) && is_red(q->link[1])) {
- /* Color flip */
- q->red = 1;
- q->link[0]->red = 0;
- q->link[1]->red = 0;
- }
-
- /* Fix red violation */
- if (is_red(q) && is_red(p)) {
- int dir2 = t->link[1] == g;
-
- if (q == p->link[last])
- t->link[dir2] = rbtree_single(g, !last);
- else
- t->link[dir2] = rbtree_double(g, !last);
- }
-
- last = dir;
- dir = tree->rb_compare(q->data, data);
-
- /* Stop if found. This check also disallows duplicates in the tree */
- if (dir == 0)
- break;
-
- dir = dir < 0;
-
- /* Move the helpers down */
- if (g != NULL)
- t = g;
-
- g = p, p = q;
- q = q->link[dir];
- }
-
- /* Update root */
- tree->root = head.link[1];
- }
-
- /* Make root black */
- tree->root->red = 0;
-
- tree->count++;
-
- return 1;
-}
-
-/* remove an item from a tree that matches given data
- * non-recursive top-down removal
- * returns 1 on successful removal
- * returns 0 if data item was not found
- */
-int rbtree_remove(struct RB_TREE *tree, const void *data)
-{
- struct RB_NODE head = { 0 }; /* False tree root */
- struct RB_NODE *q, *p, *g; /* Helpers */
- struct RB_NODE *f = NULL; /* Found item */
- int dir = 1, removed = 0;
-
- assert(tree && data);
-
- if (tree->root == NULL) {
- return 0; /* empty tree, nothing to remove */
- }
-
- /* Set up helpers */
- q = &head;
- g = p = NULL;
- q->link[1] = tree->root;
-
- /* Search and push a red down */
- while (q->link[dir] != NULL) {
- int last = dir;
-
- /* Update helpers */
- g = p, p = q;
- q = q->link[dir];
- dir = tree->rb_compare(q->data, data);
-
- /* Save found node */
- if (dir == 0)
- f = q;
-
- dir = dir < 0;
-
- /* Push the red node down */
- if (!is_red(q) && !is_red(q->link[dir])) {
- if (is_red(q->link[!dir]))
- p = p->link[last] = rbtree_single(q, dir);
- else if (!is_red(q->link[!dir])) {
- struct RB_NODE *s = p->link[!last];
-
- if (s != NULL) {
- if (!is_red(s->link[!last]) && !is_red(s->link[last])) {
- /* Color flip */
- p->red = 0;
- s->red = 1;
- q->red = 1;
- }
- else {
- int dir2 = g->link[1] == p;
-
- if (is_red(s->link[last]))
- g->link[dir2] = rbtree_double(p, last);
- else if (is_red(s->link[!last]))
- g->link[dir2] = rbtree_single(p, last);
-
- /* Ensure correct coloring */
- q->red = g->link[dir2]->red = 1;
- g->link[dir2]->link[0]->red = 0;
- g->link[dir2]->link[1]->red = 0;
- }
- }
- }
- }
- }
-
- /* Replace and remove if found */
- if (f != NULL) {
- G_free(f->data);
- f->data = q->data;
- p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
- G_free(q);
- tree->count--;
- removed = 1;
- }
- else
- G_debug(2, "RB tree: data not found in search tree");
-
- /* Update root and make it black */
- tree->root = head.link[1];
- if (tree->root != NULL)
- tree->root->red = 0;
-
- return removed;
-}
-
-/* find data item in tree
- * returns pointer to data item if found else NULL
- */
-void *rbtree_find(struct RB_TREE *tree, const void *data)
-{
- struct RB_NODE *curr_node = tree->root;
- int cmp;
-
- assert(tree && data);
-
- while (curr_node != NULL) {
- cmp = tree->rb_compare(curr_node->data, data);
- if (cmp == 0)
- return curr_node->data; /* found */
-
- curr_node = curr_node->link[cmp < 0];
- }
- return NULL;
-}
-
-/* initialize tree traversal
- * (re-)sets trav structure
- * returns 0
- */
-int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
-{
- assert(trav && tree);
-
- trav->tree = tree;
- trav->curr_node = tree->root;
- trav->first = 1;
- trav->top = 0;
-
- return 0;
-}
-
-/* traverse the tree in ascending order
- * useful to get all items in the tree non-recursively
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse(struct RB_TRAV *trav)
-{
- assert(trav);
-
- if (trav->curr_node == NULL) {
- if (trav->first)
- G_debug(1, "RB tree: empty tree");
- else
- G_debug(1, "RB tree: finished traversing");
-
- return NULL;
- }
-
- if (!trav->first)
- return rbtree_next(trav);
- else {
- trav->first = 0;
- return rbtree_first(trav);
- }
-}
-
-/* find start point to traverse the tree in ascending order
- * useful to get a selection of items in the tree
- * magnitudes faster than traversing the whole tree
- * may return first item that's smaller or first item that's larger
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
-{
- int dir = 0;
-
- assert(trav && data);
-
- if (trav->curr_node == NULL) {
- if (trav->first)
- G_warning("RB tree: empty tree");
- else
- G_warning("RB tree: finished traversing");
-
- return NULL;
- }
-
- if (!trav->first)
- return rbtree_next(trav);
-
- /* else first time, get start node */
-
- trav->first = 0;
- trav->top = 0;
-
- while (trav->curr_node != NULL) {
- dir = trav->tree->rb_compare(trav->curr_node->data, data);
- /* exact match, great! */
- if (dir == 0)
- return trav->curr_node->data;
- else {
- dir = dir < 0;
- /* end of branch, also reached if
- * smallest item is larger than search template or
- * largest item is smaller than search template */
- if (trav->curr_node->link[dir] == NULL)
- return trav->curr_node->data;
-
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[dir];
- }
- }
-
- return NULL; /* should not happen */
-}
-
-/* two functions needed to fully traverse the tree: initialize and continue
- * useful to get all items in the tree non-recursively
- * this one here uses a stack
- * parent pointers or threads would also be possible
- * but these would need to be added to RB_NODE
- * -> more memory needed for standard operations
- */
-
-/* start traversing the tree
- * returns pointer to smallest data item
- */
-void *rbtree_first(struct RB_TRAV *trav)
-{
- /* get smallest item */
- while (trav->curr_node->link[0] != NULL) {
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[0];
- }
-
- return trav->curr_node->data; /* return smallest item */
-}
-
-/* continue traversing the tree in ascending order
- * returns pointer to data item, NULL when finished
- */
-void *rbtree_next(struct RB_TRAV *trav)
-{
- if (trav->curr_node->link[1] != NULL) {
- /* something on the right side: larger item */
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[1];
-
- /* go down, find smallest item in this branch */
- while (trav->curr_node->link[0] != NULL) {
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[0];
- }
- }
- else {
- /* at smallest item in this branch, go back up */
- struct RB_NODE *last;
-
- do {
- if (trav->top == 0) {
- trav->curr_node = NULL;
- break;
- }
- last = trav->curr_node;
- trav->curr_node = trav->up[--trav->top];
- } while (last == trav->curr_node->link[1]);
- }
-
- if (trav->curr_node != NULL) {
- return trav->curr_node->data;
- }
- else
- return NULL; /* finished traversing */
-}
-
-/* destroy the tree */
-void rbtree_destroy(struct RB_TREE *tree)
-{
- rbtree_destroy2(tree->root);
- G_free(tree);
-}
-
-void rbtree_destroy2(struct RB_NODE *root)
-{
- if (root != NULL) {
- rbtree_destroy2(root->link[0]);
- rbtree_destroy2(root->link[1]);
- G_free(root->data);
- G_free(root);
- }
-}
-
-/* used for debugging: check for errors in tree structure */
-int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
-{
- int lh, rh;
-
- if (root == NULL)
- return 1;
- else {
- struct RB_NODE *ln = root->link[0];
- struct RB_NODE *rn = root->link[1];
- int lcmp = 0, rcmp = 0;
-
- /* Consecutive red links */
- if (is_red(root)) {
- if (is_red(ln) || is_red(rn)) {
- G_warning("Red Black Tree debugging: Red violation");
- return 0;
- }
- }
-
- lh = rbtree_debug(tree, ln);
- rh = rbtree_debug(tree, rn);
-
- if (ln) {
- lcmp = tree->rb_compare(ln->data, root->data);
- }
-
- if (rn) {
- rcmp = tree->rb_compare(rn->data, root->data);
- }
-
- /* Invalid binary search tree:
- * left node >= parent or right node <= parent */
- if ((ln != NULL && lcmp > -1)
- || (rn != NULL && rcmp < 1)) {
- G_warning("Red Black Tree debugging: Binary tree violation");
- return 0;
- }
-
- /* Black height mismatch */
- if (lh != 0 && rh != 0 && lh != rh) {
- G_warning("Red Black Tree debugging: Black violation");
- return 0;
- }
-
- /* Only count black links */
- if (lh != 0 && rh != 0)
- return is_red(root) ? lh : lh + 1;
- else
- return 0;
- }
-}
-
-/*******************************************************
- * *
- * internal functions for Red Black Tree maintenance *
- * *
- *******************************************************/
-
-/* add a new node to the tree */
-struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
-{
- struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
-
- if (new_node == NULL)
- G_fatal_error("RB Search Tree: Out of memory!");
-
- new_node->data = G_malloc(datasize);
- if (new_node->data == NULL)
- G_fatal_error("RB Search Tree: Out of memory!");
-
- memcpy(new_node->data, data, datasize);
- new_node->red = 1; /* 1 is red, 0 is black */
- new_node->link[0] = NULL;
- new_node->link[1] = NULL;
-
- return new_node;
-}
-
-/* check for red violation */
-int is_red(struct RB_NODE *root)
-{
- if (root)
- return root->red == 1;
-
- return 0;
-}
-
-/* single rotation */
-struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
-{
- struct RB_NODE *newroot = root->link[!dir];
-
- root->link[!dir] = newroot->link[dir];
- newroot->link[dir] = root;
-
- root->red = 1;
- newroot->red = 0;
-
- return newroot;
-}
-
-/* double rotation */
-struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
-{
- root->link[!dir] = rbtree_single(root->link[!dir], !dir);
- return rbtree_single(root, dir);
-}
Deleted: grass/trunk/lib/segment/rbtree.h
===================================================================
--- grass/trunk/lib/segment/rbtree.h 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/rbtree.h 2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,112 +0,0 @@
-/*************************************************************
- * USAGE *
- *************************************************************
- *
- * NOTE: duplicates are not supported
- *
- * custom compare function
- * extern int my_compare_fn(const void *, const void *);
- * int my_compare_fn(const void *a, const void *b) {
- * if ((mydatastruct *) a < (mydatastruct *) b)
- * return -1;
- * else if ((mydatastruct *) a > (mydatastruct *) b)
- * return 1;
- * else if ((mydatastruct *) a == (mydatastruct *) b)
- * return 0;
- * }
- *
- * create and initialize tree:
- * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
- *
- * insert items to tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_insert(mytree, &data) == 0)
- * G_warning("could not insert data");
- *
- * find item in tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_find(mytree, &data) == 0)
- * G_message("data not found");
- *
- * delete item from tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_remove(mytree, &data) == 0)
- * G_warning("could not find data in tree");
- *
- * traverse tree (get all items in tree in ascending order):
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- * if (my_compare_fn(data, threshold_data) == 0) break;
- * <do something with data>;
- * }
- *
- * get a selection of items: all data > data1 and < data2
- * start in tree where data is last smaller or first larger compared to data1
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * data = rbtree_traverse_start(&trav, &data1);
- * <do something with data>;
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- * if (data > data2) break;
- * <do something with data>;
- * }
- *
- * destroy tree:
- * rbtree_destroy(mytree);
- *
- * debug the whole tree with
- * rbtree_debug(mytree, mytree->root);
- *
- *************************************************************/
-
-#include <stddef.h>
-
-/* maximum RB Tree height */
-#define RBTREE_MAX_HEIGHT 64 /* should be more than enough */
-
-/* routine to compare data items
- * return -1 if rb_a < rb_b
- * return 0 if rb_a == rb_b
- * return 1 if rb_a > rb_b
- */
-typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
-
-struct RB_NODE
-{
- unsigned char red; /* 0 = black, 1 = red */
- void *data; /* any kind of data */
- struct RB_NODE *link[2]; /* link to children: link[0] for smaller, link[1] for larger */
-};
-
-struct RB_TREE
-{
- struct RB_NODE *root; /* root node */
- size_t datasize; /* item size */
- size_t count; /* number of items in tree. */
- rb_compare_fn *rb_compare; /* function to compare data */
-};
-
-struct RB_TRAV
-{
- struct RB_TREE *tree; /* tree being traversed */
- struct RB_NODE *curr_node; /* current node */
- struct RB_NODE *up[RBTREE_MAX_HEIGHT]; /* stack of parent nodes */
- int top; /* index for stack */
- int first; /* little helper flag */
-};
-
-/* tree functions */
-struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
-void rbtree_destroy(struct RB_TREE *);
-int rbtree_insert(struct RB_TREE *, void *);
-int rbtree_remove(struct RB_TREE *, const void *);
-void *rbtree_find(struct RB_TREE *, const void *);
-
-/* tree traversal functions */
-int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
-void* rbtree_traverse(struct RB_TRAV *);
-void *rbtree_traverse_start(struct RB_TRAV *, const void *);
-
-/* debug tree from given node downwards */
-int rbtree_debug(struct RB_TREE *, struct RB_NODE *);
Modified: grass/trunk/lib/segment/release.c
===================================================================
--- grass/trunk/lib/segment/release.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/release.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -14,7 +14,7 @@
#include <stdlib.h>
#include <grass/segment.h>
-#include "rbtree.h"
+#include <grass/rbtree.h>
/**
Modified: grass/trunk/lib/segment/setup.c
===================================================================
--- grass/trunk/lib/segment/setup.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/segment/setup.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -17,7 +17,7 @@
#include <math.h>
#include <grass/gis.h>
#include <grass/segment.h>
-#include "rbtree.h"
+#include <grass/rbtree.h>
/**
Modified: grass/trunk/lib/vector/Vlib/break_polygons.c
===================================================================
--- grass/trunk/lib/vector/Vlib/break_polygons.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/vector/Vlib/break_polygons.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -21,7 +21,6 @@
#include <math.h>
#include <grass/gis.h>
#include <grass/vector.h>
-#include <grass/vect/rbtree.h>
#include <grass/glocale.h>
/* TODO: 3D support
Modified: grass/trunk/lib/vector/Vlib/snap.c
===================================================================
--- grass/trunk/lib/vector/Vlib/snap.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/vector/Vlib/snap.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -20,7 +20,6 @@
#include <grass/gis.h>
#include <grass/vector.h>
#include <grass/glocale.h>
-#include <grass/vect/rbtree.h>
/* function prototypes */
static int sort_new(const void *pa, const void *pb);
Deleted: grass/trunk/lib/vector/diglib/rbtree.c
===================================================================
--- grass/trunk/lib/vector/diglib/rbtree.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/lib/vector/diglib/rbtree.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,536 +0,0 @@
-/*!
- * \file rbtree.c
- *
- * \brief binary search tree
- *
- * Generic balanced binary search tree (Red Black Tree) implementation
- *
- * (C) 2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2). Read the file COPYING that comes with GRASS for details.
- *
- * \author Original author Julienne Walker 2003, 2008
- * GRASS implementation Markus Metz, 2009
- */
-
-/* balanced binary search tree implementation
- *
- * this one is a Red Black Tree, the bare version, no parent pointers, no threads
- * The core code comes from Julienne Walker's tutorials on binary search trees
- * original license: public domain
- * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
- * some ideas come from libavl (GPL >= 2)
- * I could have used some off-the-shelf solution, but that's boring
- *
- * Red Black Trees are used to maintain a data structure with
- * search, insertion and deletion in O(log N) time
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include <grass/vect/rbtree.h>
-
-/* internal functions */
-void rbtree_destroy2(struct RB_NODE *);
-struct RB_NODE *rbtree_single(struct RB_NODE *, int);
-struct RB_NODE *rbtree_double(struct RB_NODE *, int);
-void *rbtree_first(struct RB_TRAV *);
-void *rbtree_next(struct RB_TRAV *);
-struct RB_NODE *rbtree_make_node(size_t, void *);
-int is_red(struct RB_NODE *);
-
-
-/* create new tree and initialize
- * returns pointer to new tree, NULL for memory allocation error
- */
-struct RB_TREE *rbtree_create(rb_compare_fn *compare, size_t rb_datasize)
-{
- struct RB_TREE *tree = G_malloc(sizeof(*tree));
-
- if (tree == NULL) {
- G_warning("RB tree: Out of memory!");
- return NULL;
- }
-
- assert(compare);
-
- tree->datasize = rb_datasize;
- tree->rb_compare = compare;
- tree->count = 0;
- tree->root = NULL;
-
- return tree;
-}
-
-/* add an item to a tree
- * non-recursive top-down insertion
- * the algorithm does not allow duplicates and also does not warn about a duplicate
- * returns 1 on success, 0 on failure
- */
-int rbtree_insert(struct RB_TREE *tree, void *data)
-{
- assert(tree && data);
-
- if (tree->root == NULL) {
- /* create a new root node for tree */
- tree->root = rbtree_make_node(tree->datasize, data);
- if (tree->root == NULL)
- return 0;
- }
- else {
- struct RB_NODE head = {0}; /* False tree root */
-
- struct RB_NODE *g, *t; /* Grandparent & parent */
- struct RB_NODE *p, *q; /* Iterator & parent */
- int dir = 0, last = 0;
-
- /* Set up helpers */
- t = &head;
- g = p = NULL;
- q = t->link[1] = tree->root;
-
- /* Search down the tree */
- for ( ; ; ) {
- if (q == NULL) {
- /* Insert new node at the bottom */
- p->link[dir] = q = rbtree_make_node(tree->datasize, data);
- if (q == NULL)
- return 0;
- }
- else if (is_red(q->link[0]) && is_red(q->link[1])) {
- /* Color flip */
- q->red = 1;
- q->link[0]->red = 0;
- q->link[1]->red = 0;
- }
-
- /* Fix red violation */
- if (is_red(q) && is_red(p)) {
- int dir2 = t->link[1] == g;
-
- if (q == p->link[last])
- t->link[dir2] = rbtree_single(g, !last);
- else
- t->link[dir2] = rbtree_double(g, !last);
- }
-
- last = dir;
- dir = tree->rb_compare(q->data, data);
-
- /* Stop if found. This check also disallows duplicates in the tree */
- if (dir == 0)
- break;
-
- dir = dir < 0;
-
- /* Move the helpers down */
- if (g != NULL)
- t = g;
-
- g = p, p = q;
- q = q->link[dir];
- }
-
- /* Update root */
- tree->root = head.link[1];
- }
-
- /* Make root black */
- tree->root->red = 0;
-
- tree->count++;
-
- return 1;
-}
-
-/* remove an item from a tree that matches given data
- * non-recursive top-down removal
- * returns 1 on successful removal
- * returns 0 if data item was not found
- */
-int rbtree_remove(struct RB_TREE *tree, const void *data)
-{
- struct RB_NODE head = {0}; /* False tree root */
- struct RB_NODE *q, *p, *g; /* Helpers */
- struct RB_NODE *f = NULL; /* Found item */
- int dir = 1, removed = 0;
-
- assert(tree && data);
-
- if (tree->root == NULL) {
- return 0; /* empty tree, nothing to remove */
- }
-
- /* Set up helpers */
- q = &head;
- g = p = NULL;
- q->link[1] = tree->root;
-
- /* Search and push a red down */
- while (q->link[dir] != NULL) {
- int last = dir;
-
- /* Update helpers */
- g = p, p = q;
- q = q->link[dir];
- dir = tree->rb_compare(q->data, data);
-
- /* Save found node */
- if (dir == 0)
- f = q;
-
- dir = dir < 0;
-
- /* Push the red node down */
- if (!is_red(q) && !is_red(q->link[dir])) {
- if (is_red(q->link[!dir]))
- p = p->link[last] = rbtree_single(q, dir);
- else if (!is_red(q->link[!dir])) {
- struct RB_NODE *s = p->link[!last];
-
- if (s != NULL) {
- if (!is_red(s->link[!last]) &&
- !is_red(s->link[last])) {
- /* Color flip */
- p->red = 0;
- s->red = 1;
- q->red = 1;
- }
- else {
- int dir2 = g->link[1] == p;
-
- if (is_red(s->link[last]))
- g->link[dir2] = rbtree_double(p, last);
- else if (is_red(s->link[!last]))
- g->link[dir2] = rbtree_single(p, last);
-
- /* Ensure correct coloring */
- q->red = g->link[dir2]->red = 1;
- g->link[dir2]->link[0]->red = 0;
- g->link[dir2]->link[1]->red = 0;
- }
- }
- }
- }
- }
-
- /* Replace and remove if found */
- if (f != NULL) {
- G_free(f->data);
- f->data = q->data;
- p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
- G_free(q);
- tree->count--;
- removed = 1;
- }
- else
- G_debug(2, "RB tree: data not found in search tree");
-
- /* Update root and make it black */
- tree->root = head.link[1];
- if ( tree->root != NULL)
- tree->root->red = 0;
-
- return removed;
-}
-
-/* find data item in tree
- * returns pointer to data item if found else NULL
- */
-void *rbtree_find(struct RB_TREE *tree, const void *data)
-{
- struct RB_NODE *curr_node = tree->root;
- int cmp = 0;
-
- assert(tree && data);
-
- while (curr_node != NULL) {
- cmp = tree->rb_compare(curr_node->data, data);
- if (cmp == 0)
- return curr_node->data; /* found */
- else {
- curr_node = curr_node->link[cmp < 0];
- }
- }
- return NULL;
-}
-
-/* initialize tree traversal
- * (re-)sets trav structure
- * returns 0
- */
-int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
-{
- assert(trav && tree);
-
- trav->tree = tree;
- trav->curr_node = tree->root;
- trav->first = 1;
- trav->top = 0;
-
- return 0;
-}
-
-/* traverse the tree in ascending order
- * useful to get all items in the tree non-recursively
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse(struct RB_TRAV *trav)
-{
- assert(trav);
-
- if (trav->curr_node == NULL) {
- if (trav->first)
- G_debug(1, "RB tree: empty tree");
- else
- G_debug(1, "RB tree: finished traversing");
-
- return NULL;
- }
-
- if (!trav->first)
- return rbtree_next(trav);
- else {
- trav->first = 0;
- return rbtree_first(trav);
- }
-}
-
-/* find start point to traverse the tree in ascending order
- * useful to get a selection of items in the tree
- * magnitudes faster than traversing the whole tree
- * may return first item that's smaller or first item that's larger
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
-{
- int dir = 0;
-
- assert(trav && data);
-
- if (trav->curr_node == NULL) {
- if (trav->first)
- G_warning("RB tree: empty tree");
- else
- G_warning("RB tree: finished traversing");
-
- return NULL;
- }
-
- if (!trav->first)
- return rbtree_next(trav);
-
- /* else first time, get start node */
-
- trav->first = 0;
- trav->top = 0;
-
- while (trav->curr_node != NULL) {
- dir = trav->tree->rb_compare(trav->curr_node->data, data);
- /* exact match, great! */
- if (dir == 0)
- return trav->curr_node->data;
- else {
- dir = dir < 0;
- /* end of branch, also reached if
- * smallest item is larger than search template or
- * largest item is smaller than search template */
- if (trav->curr_node->link[dir] == NULL)
- return trav->curr_node->data;
-
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[dir];
- }
- }
-
- return NULL; /* should not happen */
-}
-
-/* two functions needed to fully traverse the tree: initialize and continue
- * useful to get all items in the tree non-recursively
- * this one here uses a stack
- * parent pointers or threads would also be possible
- * but these would need to be added to RB_NODE
- * -> more memory needed for standard operations
- */
-
-/* start traversing the tree
- * returns pointer to smallest data item
- */
-void *rbtree_first(struct RB_TRAV *trav)
-{
- /* get smallest item */
- while (trav->curr_node->link[0] != NULL) {
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[0];
- }
-
- return trav->curr_node->data; /* return smallest item */
-}
-
-/* continue traversing the tree in ascending order
- * returns pointer to data item, NULL when finished
- */
-void *rbtree_next(struct RB_TRAV *trav)
-{
- if (trav->curr_node->link[1] != NULL) {
- /* something on the right side: larger item */
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[1];
-
- /* go down, find smallest item in this branch */
- while (trav->curr_node->link[0] != NULL) {
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[0];
- }
- }
- else {
- /* at smallest item in this branch, go back up */
- struct RB_NODE *last;
- do {
- if (trav->top == 0) {
- trav->curr_node = NULL;
- break;
- }
- last = trav->curr_node;
- trav->curr_node = trav->up[--trav->top];
- } while (last == trav->curr_node->link[1]);
- }
-
- if (trav->curr_node != NULL) {
- return trav->curr_node->data;
- }
- else
- return NULL; /* finished traversing */
-}
-
-/* destroy the tree */
-void rbtree_destroy(struct RB_TREE *tree) {
- rbtree_destroy2(tree->root);
- G_free(tree);
-}
-
-void rbtree_destroy2(struct RB_NODE *root)
-{
- if (root != NULL) {
- rbtree_destroy2(root->link[0]);
- rbtree_destroy2(root->link[1]);
- G_free(root->data);
- G_free(root);
- }
-}
-
-/* used for debugging: check for errors in tree structure */
-int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
-{
- int lh, rh;
-
- if (root == NULL)
- return 1;
- else {
- struct RB_NODE *ln = root->link[0];
- struct RB_NODE *rn = root->link[1];
- int lcmp = 0, rcmp = 0;
-
- /* Consecutive red links */
- if (is_red(root)) {
- if (is_red(ln) || is_red(rn)) {
- G_warning("Red Black Tree debugging: Red violation");
- return 0;
- }
- }
-
- lh = rbtree_debug(tree, ln);
- rh = rbtree_debug(tree, rn);
-
- if (ln) {
- lcmp = tree->rb_compare(ln->data, root->data);
- }
-
- if (rn) {
- rcmp = tree->rb_compare(rn->data, root->data);
- }
-
- /* Invalid binary search tree:
- * left node >= parent or right node <= parent */
- if ((ln != NULL && lcmp > -1)
- || (rn != NULL && rcmp < 1)) {
- G_warning("Red Black Tree debugging: Binary tree violation" );
- return 0;
- }
-
- /* Black height mismatch */
- if (lh != 0 && rh != 0 && lh != rh) {
- G_warning("Red Black Tree debugging: Black violation");
- return 0;
- }
-
- /* Only count black links */
- if (lh != 0 && rh != 0)
- return is_red(root) ? lh : lh + 1;
- else
- return 0;
- }
-}
-
-/*******************************************************
- * *
- * internal functions for Red Black Tree maintenance *
- * *
- *******************************************************/
-
-/* add a new node to the tree */
-struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
-{
- struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
-
- if (new_node == NULL)
- G_fatal_error("RB Search Tree: Out of memory!");
-
- new_node->data = G_malloc(datasize);
- if (new_node->data == NULL)
- G_fatal_error("RB Search Tree: Out of memory!");
-
- memcpy(new_node->data, data, datasize);
- new_node->red = 1; /* 1 is red, 0 is black */
- new_node->link[0] = NULL;
- new_node->link[1] = NULL;
-
- return new_node;
-}
-
-/* check for red violation */
-int is_red(struct RB_NODE *root)
-{
- if (root)
- return root->red == 1;
-
- return 0;
-}
-
-/* single rotation */
-struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
-{
- struct RB_NODE *newroot = root->link[!dir];
-
- root->link[!dir] = newroot->link[dir];
- newroot->link[dir] = root;
-
- root->red = 1;
- newroot->red = 0;
-
- return newroot;
-}
-
-/* double rotation */
-struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
-{
- root->link[!dir] = rbtree_single(root->link[!dir], !dir);
- return rbtree_single(root, dir);
-}
Modified: grass/trunk/raster/r.watershed/ram/Makefile
===================================================================
--- grass/trunk/raster/r.watershed/ram/Makefile 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/Makefile 2010-05-18 09:42:14 UTC (rev 42281)
@@ -2,7 +2,7 @@
PGM = r.watershed.ram
-LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB)
+LIBES = $(RASTERLIB) $(GISLIB) $(MATHLIB) $(BTREE2LIB)
DEPENDENCIES = $(RASTERDEP) $(GISDEP)
include $(MODULE_TOPDIR)/include/Make/Etc.make
Modified: grass/trunk/raster/r.watershed/ram/do_flatarea.c
===================================================================
--- grass/trunk/raster/r.watershed/ram/do_flatarea.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/do_flatarea.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -16,9 +16,9 @@
#include <assert.h>
#include <grass/gis.h>
#include <grass/glocale.h>
+#include <grass/rbtree.h>
#include "Gwater.h"
#include "do_astar.h"
-#include "rbtree.h"
struct pq_node
{
Deleted: grass/trunk/raster/r.watershed/ram/rbtree.c
===================================================================
--- grass/trunk/raster/r.watershed/ram/rbtree.c 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/rbtree.c 2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,535 +0,0 @@
-/*!
- * \file rbtree.c
- *
- * \brief binary search tree
- *
- * Generic balanced binary search tree (Red Black Tree) implementation
- *
- * (C) 2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public License
- * (>=v2). Read the file COPYING that comes with GRASS for details.
- *
- * \author Original author Julienne Walker 2003, 2008
- * GRASS implementation Markus Metz, 2009
- */
-
-/* balanced binary search tree implementation
- *
- * this one is a Red Black Tree, the bare version, no parent pointers, no threads
- * The core code comes from Julienne Walker's tutorials on binary search trees
- * original license: public domain
- * http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
- * some ideas come from libavl (GPL >= 2)
- * I could have used some off-the-shelf solution, but that's boring
- *
- * Red Black Trees are used to maintain a data structure with
- * search, insertion and deletion in O(log N) time
- */
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <grass/gis.h>
-#include <grass/glocale.h>
-#include "rbtree.h"
-
-/* internal functions */
-void rbtree_destroy2(struct RB_NODE *);
-struct RB_NODE *rbtree_single(struct RB_NODE *, int);
-struct RB_NODE *rbtree_double(struct RB_NODE *, int);
-void *rbtree_first(struct RB_TRAV *);
-void *rbtree_next(struct RB_TRAV *);
-struct RB_NODE *rbtree_make_node(size_t, void *);
-int is_red(struct RB_NODE *);
-
-
-/* create new tree and initialize
- * returns pointer to new tree, NULL for memory allocation error
- */
-struct RB_TREE *rbtree_create(rb_compare_fn * compare, size_t rb_datasize)
-{
- struct RB_TREE *tree = G_malloc(sizeof(*tree));
-
- if (tree == NULL) {
- G_warning("RB tree: Out of memory!");
- return NULL;
- }
-
- assert(compare);
-
- tree->datasize = rb_datasize;
- tree->rb_compare = compare;
- tree->count = 0;
- tree->root = NULL;
-
- return tree;
-}
-
-/* add an item to a tree
- * non-recursive top-down insertion
- * the algorithm does not allow duplicates and also does not warn about a duplicate
- * returns 1 on success, 0 on failure
- */
-int rbtree_insert(struct RB_TREE *tree, void *data)
-{
- assert(tree && data);
-
- if (tree->root == NULL) {
- /* create a new root node for tree */
- tree->root = rbtree_make_node(tree->datasize, data);
- if (tree->root == NULL)
- return 0;
- }
- else {
- struct RB_NODE head = { 0 }; /* False tree root */
- struct RB_NODE *g, *t; /* Grandparent & parent */
- struct RB_NODE *p, *q; /* Iterator & parent */
- int dir = 0, last = 0;
-
- /* Set up helpers */
- t = &head;
- g = p = NULL;
- q = t->link[1] = tree->root;
-
- /* Search down the tree */
- for (;;) {
- if (q == NULL) {
- /* Insert new node at the bottom */
- p->link[dir] = q = rbtree_make_node(tree->datasize, data);
- if (q == NULL)
- return 0;
- }
- else if (is_red(q->link[0]) && is_red(q->link[1])) {
- /* Color flip */
- q->red = 1;
- q->link[0]->red = 0;
- q->link[1]->red = 0;
- }
-
- /* Fix red violation */
- if (is_red(q) && is_red(p)) {
- int dir2 = t->link[1] == g;
-
- if (q == p->link[last])
- t->link[dir2] = rbtree_single(g, !last);
- else
- t->link[dir2] = rbtree_double(g, !last);
- }
-
- last = dir;
- dir = tree->rb_compare(q->data, data);
-
- /* Stop if found. This check also disallows duplicates in the tree */
- if (dir == 0)
- break;
-
- dir = dir < 0;
-
- /* Move the helpers down */
- if (g != NULL)
- t = g;
-
- g = p, p = q;
- q = q->link[dir];
- }
-
- /* Update root */
- tree->root = head.link[1];
- }
-
- /* Make root black */
- tree->root->red = 0;
-
- tree->count++;
-
- return 1;
-}
-
-/* remove an item from a tree that matches given data
- * non-recursive top-down removal
- * returns 1 on successful removal
- * returns 0 if data item was not found
- */
-int rbtree_remove(struct RB_TREE *tree, const void *data)
-{
- struct RB_NODE head = { 0 }; /* False tree root */
- struct RB_NODE *q, *p, *g; /* Helpers */
- struct RB_NODE *f = NULL; /* Found item */
- int dir = 1, removed = 0;
-
- assert(tree && data);
-
- if (tree->root == NULL) {
- return 0; /* empty tree, nothing to remove */
- }
-
- /* Set up helpers */
- q = &head;
- g = p = NULL;
- q->link[1] = tree->root;
-
- /* Search and push a red down */
- while (q->link[dir] != NULL) {
- int last = dir;
-
- /* Update helpers */
- g = p, p = q;
- q = q->link[dir];
- dir = tree->rb_compare(q->data, data);
-
- /* Save found node */
- if (dir == 0)
- f = q;
-
- dir = dir < 0;
-
- /* Push the red node down */
- if (!is_red(q) && !is_red(q->link[dir])) {
- if (is_red(q->link[!dir]))
- p = p->link[last] = rbtree_single(q, dir);
- else if (!is_red(q->link[!dir])) {
- struct RB_NODE *s = p->link[!last];
-
- if (s != NULL) {
- if (!is_red(s->link[!last]) && !is_red(s->link[last])) {
- /* Color flip */
- p->red = 0;
- s->red = 1;
- q->red = 1;
- }
- else {
- int dir2 = g->link[1] == p;
-
- if (is_red(s->link[last]))
- g->link[dir2] = rbtree_double(p, last);
- else if (is_red(s->link[!last]))
- g->link[dir2] = rbtree_single(p, last);
-
- /* Ensure correct coloring */
- q->red = g->link[dir2]->red = 1;
- g->link[dir2]->link[0]->red = 0;
- g->link[dir2]->link[1]->red = 0;
- }
- }
- }
- }
- }
-
- /* Replace and remove if found */
- if (f != NULL) {
- G_free(f->data);
- f->data = q->data;
- p->link[p->link[1] == q] = q->link[q->link[0] == NULL];
- G_free(q);
- tree->count--;
- removed = 1;
- }
- else
- G_debug(2, "RB tree: data not found in search tree");
-
- /* Update root and make it black */
- tree->root = head.link[1];
- if (tree->root != NULL)
- tree->root->red = 0;
-
- return removed;
-}
-
-/* find data item in tree
- * returns pointer to data item if found else NULL
- */
-void *rbtree_find(struct RB_TREE *tree, const void *data)
-{
- struct RB_NODE *curr_node = tree->root;
- int cmp;
-
- assert(tree && data);
-
- while (curr_node != NULL) {
- cmp = tree->rb_compare(curr_node->data, data);
- if (cmp == 0)
- return curr_node->data; /* found */
-
- curr_node = curr_node->link[cmp < 0];
- }
- return NULL;
-}
-
-/* initialize tree traversal
- * (re-)sets trav structure
- * returns 0
- */
-int rbtree_init_trav(struct RB_TRAV *trav, struct RB_TREE *tree)
-{
- assert(trav && tree);
-
- trav->tree = tree;
- trav->curr_node = tree->root;
- trav->first = 1;
- trav->top = 0;
-
- return 0;
-}
-
-/* traverse the tree in ascending order
- * useful to get all items in the tree non-recursively
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse(struct RB_TRAV *trav)
-{
- assert(trav);
-
- if (trav->curr_node == NULL) {
- if (trav->first)
- G_debug(1, "RB tree: empty tree");
- else
- G_debug(1, "RB tree: finished traversing");
-
- return NULL;
- }
-
- if (!trav->first)
- return rbtree_next(trav);
- else {
- trav->first = 0;
- return rbtree_first(trav);
- }
-}
-
-/* find start point to traverse the tree in ascending order
- * useful to get a selection of items in the tree
- * magnitudes faster than traversing the whole tree
- * may return first item that's smaller or first item that's larger
- * struct RB_TRAV *trav needs to be initialized first
- * returns pointer to data, NULL when finished
- */
-void *rbtree_traverse_start(struct RB_TRAV *trav, const void *data)
-{
- int dir = 0;
-
- assert(trav && data);
-
- if (trav->curr_node == NULL) {
- if (trav->first)
- G_warning("RB tree: empty tree");
- else
- G_warning("RB tree: finished traversing");
-
- return NULL;
- }
-
- if (!trav->first)
- return rbtree_next(trav);
-
- /* else first time, get start node */
-
- trav->first = 0;
- trav->top = 0;
-
- while (trav->curr_node != NULL) {
- dir = trav->tree->rb_compare(trav->curr_node->data, data);
- /* exact match, great! */
- if (dir == 0)
- return trav->curr_node->data;
- else {
- dir = dir < 0;
- /* end of branch, also reached if
- * smallest item is larger than search template or
- * largest item is smaller than search template */
- if (trav->curr_node->link[dir] == NULL)
- return trav->curr_node->data;
-
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[dir];
- }
- }
-
- return NULL; /* should not happen */
-}
-
-/* two functions needed to fully traverse the tree: initialize and continue
- * useful to get all items in the tree non-recursively
- * this one here uses a stack
- * parent pointers or threads would also be possible
- * but these would need to be added to RB_NODE
- * -> more memory needed for standard operations
- */
-
-/* start traversing the tree
- * returns pointer to smallest data item
- */
-void *rbtree_first(struct RB_TRAV *trav)
-{
- /* get smallest item */
- while (trav->curr_node->link[0] != NULL) {
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[0];
- }
-
- return trav->curr_node->data; /* return smallest item */
-}
-
-/* continue traversing the tree in ascending order
- * returns pointer to data item, NULL when finished
- */
-void *rbtree_next(struct RB_TRAV *trav)
-{
- if (trav->curr_node->link[1] != NULL) {
- /* something on the right side: larger item */
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[1];
-
- /* go down, find smallest item in this branch */
- while (trav->curr_node->link[0] != NULL) {
- trav->up[trav->top++] = trav->curr_node;
- trav->curr_node = trav->curr_node->link[0];
- }
- }
- else {
- /* at smallest item in this branch, go back up */
- struct RB_NODE *last;
-
- do {
- if (trav->top == 0) {
- trav->curr_node = NULL;
- break;
- }
- last = trav->curr_node;
- trav->curr_node = trav->up[--trav->top];
- } while (last == trav->curr_node->link[1]);
- }
-
- if (trav->curr_node != NULL) {
- return trav->curr_node->data;
- }
- else
- return NULL; /* finished traversing */
-}
-
-/* destroy the tree */
-void rbtree_destroy(struct RB_TREE *tree)
-{
- rbtree_destroy2(tree->root);
- G_free(tree);
-}
-
-void rbtree_destroy2(struct RB_NODE *root)
-{
- if (root != NULL) {
- rbtree_destroy2(root->link[0]);
- rbtree_destroy2(root->link[1]);
- G_free(root->data);
- G_free(root);
- }
-}
-
-/* used for debugging: check for errors in tree structure */
-int rbtree_debug(struct RB_TREE *tree, struct RB_NODE *root)
-{
- int lh, rh;
-
- if (root == NULL)
- return 1;
- else {
- struct RB_NODE *ln = root->link[0];
- struct RB_NODE *rn = root->link[1];
- int lcmp = 0, rcmp = 0;
-
- /* Consecutive red links */
- if (is_red(root)) {
- if (is_red(ln) || is_red(rn)) {
- G_warning("Red Black Tree debugging: Red violation");
- return 0;
- }
- }
-
- lh = rbtree_debug(tree, ln);
- rh = rbtree_debug(tree, rn);
-
- if (ln) {
- lcmp = tree->rb_compare(ln->data, root->data);
- }
-
- if (rn) {
- rcmp = tree->rb_compare(rn->data, root->data);
- }
-
- /* Invalid binary search tree:
- * left node >= parent or right node <= parent */
- if ((ln != NULL && lcmp > -1)
- || (rn != NULL && rcmp < 1)) {
- G_warning("Red Black Tree debugging: Binary tree violation");
- return 0;
- }
-
- /* Black height mismatch */
- if (lh != 0 && rh != 0 && lh != rh) {
- G_warning("Red Black Tree debugging: Black violation");
- return 0;
- }
-
- /* Only count black links */
- if (lh != 0 && rh != 0)
- return is_red(root) ? lh : lh + 1;
- else
- return 0;
- }
-}
-
-/*******************************************************
- * *
- * internal functions for Red Black Tree maintenance *
- * *
- *******************************************************/
-
-/* add a new node to the tree */
-struct RB_NODE *rbtree_make_node(size_t datasize, void *data)
-{
- struct RB_NODE *new_node = G_malloc(sizeof(*new_node));
-
- if (new_node == NULL)
- G_fatal_error("RB Search Tree: Out of memory!");
-
- new_node->data = G_malloc(datasize);
- if (new_node->data == NULL)
- G_fatal_error("RB Search Tree: Out of memory!");
-
- memcpy(new_node->data, data, datasize);
- new_node->red = 1; /* 1 is red, 0 is black */
- new_node->link[0] = NULL;
- new_node->link[1] = NULL;
-
- return new_node;
-}
-
-/* check for red violation */
-int is_red(struct RB_NODE *root)
-{
- if (root)
- return root->red == 1;
-
- return 0;
-}
-
-/* single rotation */
-struct RB_NODE *rbtree_single(struct RB_NODE *root, int dir)
-{
- struct RB_NODE *newroot = root->link[!dir];
-
- root->link[!dir] = newroot->link[dir];
- newroot->link[dir] = root;
-
- root->red = 1;
- newroot->red = 0;
-
- return newroot;
-}
-
-/* double rotation */
-struct RB_NODE *rbtree_double(struct RB_NODE *root, int dir)
-{
- root->link[!dir] = rbtree_single(root->link[!dir], !dir);
- return rbtree_single(root, dir);
-}
Deleted: grass/trunk/raster/r.watershed/ram/rbtree.h
===================================================================
--- grass/trunk/raster/r.watershed/ram/rbtree.h 2010-05-18 09:04:38 UTC (rev 42280)
+++ grass/trunk/raster/r.watershed/ram/rbtree.h 2010-05-18 09:42:14 UTC (rev 42281)
@@ -1,112 +0,0 @@
-/*************************************************************
- * USAGE *
- *************************************************************
- *
- * NOTE: duplicates are not supported
- *
- * custom compare function
- * extern int my_compare_fn(const void *, const void *);
- * int my_compare_fn(const void *a, const void *b) {
- * if ((mydatastruct *) a < (mydatastruct *) b)
- * return -1;
- * else if ((mydatastruct *) a > (mydatastruct *) b)
- * return 1;
- * else if ((mydatastruct *) a == (mydatastruct *) b)
- * return 0;
- * }
- *
- * create and initialize tree:
- * struct RB_TREE *mytree = rbtree_create(my_compare_fn, item_size);
- *
- * insert items to tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_insert(mytree, &data) == 0)
- * G_warning("could not insert data");
- *
- * find item in tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_find(mytree, &data) == 0)
- * G_message("data not found");
- *
- * delete item from tree:
- * struct mydatastruct data = <some data>;
- * if (rbtree_remove(mytree, &data) == 0)
- * G_warning("could not find data in tree");
- *
- * traverse tree (get all items in tree in ascending order):
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- * if (my_compare_fn(data, threshold_data) == 0) break;
- * <do something with data>;
- * }
- *
- * get a selection of items: all data > data1 and < data2
- * start in tree where data is last smaller or first larger compared to data1
- * struct RB_TRAV trav;
- * rbtree_init_trav(&trav, tree);
- * data = rbtree_traverse_start(&trav, &data1);
- * <do something with data>;
- * while ((data = rbtree_traverse(&trav)) != NULL) {
- * if (data > data2) break;
- * <do something with data>;
- * }
- *
- * destroy tree:
- * rbtree_destroy(mytree);
- *
- * debug the whole tree with
- * rbtree_debug(mytree, mytree->root);
- *
- *************************************************************/
-
-#include <stddef.h>
-
-/* maximum RB Tree height */
-#define RBTREE_MAX_HEIGHT 64 /* should be more than enough */
-
-/* routine to compare data items
- * return -1 if rb_a < rb_b
- * return 0 if rb_a == rb_b
- * return 1 if rb_a > rb_b
- */
-typedef int rb_compare_fn(const void *rb_a, const void *rb_b);
-
-struct RB_NODE
-{
- unsigned char red; /* 0 = black, 1 = red */
- void *data; /* any kind of data */
- struct RB_NODE *link[2]; /* link to children: link[0] for smaller, link[1] for larger */
-};
-
-struct RB_TREE
-{
- struct RB_NODE *root; /* root node */
- size_t datasize; /* item size */
- size_t count; /* number of items in tree. */
- rb_compare_fn *rb_compare; /* function to compare data */
-};
-
-struct RB_TRAV
-{
- struct RB_TREE *tree; /* tree being traversed */
- struct RB_NODE *curr_node; /* current node */
- struct RB_NODE *up[RBTREE_MAX_HEIGHT]; /* stack of parent nodes */
- int top; /* index for stack */
- int first; /* little helper flag */
-};
-
-/* tree functions */
-struct RB_TREE *rbtree_create(rb_compare_fn *, size_t);
-void rbtree_destroy(struct RB_TREE *);
-int rbtree_insert(struct RB_TREE *, void *);
-int rbtree_remove(struct RB_TREE *, const void *);
-void *rbtree_find(struct RB_TREE *, const void *);
-
-/* tree traversal functions */
-int rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
-void* rbtree_traverse(struct RB_TRAV *);
-void *rbtree_traverse_start(struct RB_TRAV *, const void *);
-
-/* debug tree from given node downwards */
-int rbtree_debug(struct RB_TREE *, struct RB_NODE *);
More information about the grass-commit
mailing list