|
@@ -1,5 +1,5 @@
|
|
|
/*************************************************************
|
|
|
- * USAGE
|
|
|
+ * USAGE *
|
|
|
*************************************************************
|
|
|
*
|
|
|
* NOTE: duplicates are not supported
|
|
@@ -7,12 +7,12 @@
|
|
|
* 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 0;
|
|
|
- * else if ((mydatastruct *) a < (mydatastruct *) b)
|
|
|
- * return 1;
|
|
|
- * else if ((mydatastruct *) a == (mydatastruct *) b)
|
|
|
- * return 2;
|
|
|
+ * 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:
|
|
@@ -20,77 +20,93 @@
|
|
|
*
|
|
|
* insert items to tree:
|
|
|
* struct mydatastruct data = <some data>;
|
|
|
- * if (rbtree_insert(&mytree, &data) == 0)
|
|
|
- * G_warning("could not insert 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");
|
|
|
+ * 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");
|
|
|
+ * 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>;
|
|
|
+ * 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);
|
|
|
*
|
|
|
*************************************************************/
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-/* structures and functions needed for Red Black Tree */
|
|
|
-
|
|
|
#include <stddef.h>
|
|
|
|
|
|
/* maximum RB Tree height */
|
|
|
-#define RBTREE_MAX_HEIGHT 64 /* allow 2^64 items */
|
|
|
+#define RBTREE_MAX_HEIGHT 64 /* should be more than enough */
|
|
|
|
|
|
-/* routine to compare data items */
|
|
|
-/* return 0 if rb_a > rb_b */
|
|
|
-/* return 1 if rb_a < rb_b */
|
|
|
-/* return 2 if rb_a == rb_b */
|
|
|
+/* 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;
|
|
|
- void *data;
|
|
|
- struct RB_NODE *link[2];
|
|
|
+ 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;
|
|
|
+ struct RB_NODE *root; /* root node */
|
|
|
size_t datasize; /* item size */
|
|
|
- size_t count; /* Number of items in tree. */
|
|
|
- rb_compare_fn *rb_compare;
|
|
|
+ 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;
|
|
|
- struct RB_NODE *up[RBTREE_MAX_HEIGHT];
|
|
|
- int top;
|
|
|
- int first;
|
|
|
+ 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 */
|
|
|
};
|
|
|
|
|
|
-/* rbtree.c */
|
|
|
+/* 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 *);
|
|
|
-void *rbtree_find(struct RB_TREE *, const void *);
|
|
|
int rbtree_remove(struct RB_TREE *, const void *);
|
|
|
-void rbtree_init_trav(struct RB_TRAV *, struct RB_TREE *);
|
|
|
+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_destroy(struct RB_TREE *);
|
|
|
+void *rbtree_traverse_start(struct RB_TRAV *, const void *);
|
|
|
+
|
|
|
+/* debug tree from given node downwards */
|
|
|
int rbtree_debug(struct RB_TREE *, struct RB_NODE *);
|