30 #ifndef PSPLAY_TRAIL_DEPTH 31 #define PSPLAY_TRAIL_DEPTH 128 46 #define PSPLAY_FORMULA (self->log2*100/(depth + (psplay_fast_prng () & 63)) + trail->dir) * splayfactor 48 #ifndef PSPLAY_PROB_ZIGZIG 49 #define PSPLAY_PROB_ZIGZIG 5000 51 #ifndef PSPLAY_PROB_ZIGZAG 52 #define PSPLAY_PROB_ZIGZAG 2500 58 static inline uint32_t psplay_fast_prng ()
60 static uint32_t rnd=0xbabeface;
61 return rnd = rnd<<1 ^ ((rnd >> 30) & 1) ^ ((rnd>>2) & 1);
76 self->found_parent = &
self->tree;
90 PSplay
self = malloc (
sizeof *
self);
104 if (
self)
while (self->tree)
125 self->left =
self->right = NULL;
146 PSplaynode* trail[PSPLAY_TRAIL_DEPTH];
149 static inline unsigned 150 trailidx (
unsigned n)
152 return n & (PSPLAY_TRAIL_DEPTH-1);
157 psplay_splay (PSplay
self,
struct psplaytrail* trail,
unsigned splayfactor)
159 TRACE (psplay_dbg,
"%p %u",
self, splayfactor);
161 if (trail->dir < 0) trail->dir = - trail->dir;
163 for (
unsigned lim = PSPLAY_TRAIL_DEPTH, depth = trail->depth; lim > 2 && depth > 2; lim-=2, depth-=2)
165 PSplaynode node = *trail->trail [trailidx (depth)];
166 PSplaynode parent = *trail->trail [trailidx (depth-1)];
167 PSplaynode grandparent = *trail->trail [trailidx (depth-2)];
169 unsigned r = PSPLAY_FORMULA;
170 TRACE (psplay_dbg,
"r is %u", r);
172 if (parent == grandparent->left)
174 TRACE (psplay_dbg,
"ZIG..");
175 if (node == parent->left)
177 TRACE (psplay_dbg,
"..ZIG");
178 if (r < PSPLAY_PROB_ZIGZIG)
180 TRACE (psplay_dbg,
"BREAK");
184 grandparent->left = parent->right;
185 parent->right = grandparent;
187 parent->left = node->right;
188 node->right = parent;
192 TRACE (psplay_dbg,
"..ZAG");
193 if (r < PSPLAY_PROB_ZIGZAG)
195 TRACE (psplay_dbg,
"BREAK");
199 parent->right = node->left;
202 grandparent->left = node->right;
203 node->right = grandparent;
208 TRACE (psplay_dbg,
"ZAG..");
209 if (node == parent->left)
211 TRACE (psplay_dbg,
"..ZIG");
212 if (r < PSPLAY_PROB_ZIGZAG)
214 TRACE (psplay_dbg,
"BREAK");
218 parent->left = node->right;
219 node->right = parent;
221 grandparent->right = node->left;
222 node->left = grandparent;
226 TRACE (psplay_dbg,
"..ZAG");
227 if (r < PSPLAY_PROB_ZIGZIG)
229 TRACE (psplay_dbg,
"BREAK");
233 grandparent->right = parent->left;
234 parent->left = grandparent;
236 parent->right = node->left;
240 *trail->trail [trailidx (depth-2)] = node;
249 PSplaynode n =
self->tree;
254 trail.trail [0] = &
self->tree;
263 c =
self->cmp (self->key (node),
self->key (n));
271 trail.trail [trailidx (trail.depth)] = &n->left;
279 trail.trail [trailidx (trail.depth)] = &n->right;
284 WARN (psplay_dbg,
"dropping duplicate entry for psplay");
291 if (self->elem_cnt >= 1UL<<self->log2) ++
self->log2;
292 if (splayfactor && trail.depth > 2)
293 psplay_splay (
self, &trail, splayfactor);
303 PSplaynode node =
self->tree;
307 trail.trail [0] = &
self->tree;
312 c =
self->cmp (key, self->key (node));
318 trail.trail [trailidx (trail.depth)] = &node->left;
324 trail.trail [trailidx (trail.depth)] = &node->right;
329 self->found_parent = trail.trail [trailidx (--trail.depth)];
333 if (node && splayfactor && trail.depth > 2)
334 psplay_splay (
self, &trail, splayfactor);
343 if (!node)
return NULL;
345 PSplaynode* r =
self->found_parent;
351 WARN (psplay_dbg,
"node %p is not in splay tree %p", node,
self);
354 r =
self->found_parent;
359 else if (!node->right)
363 PSplaynode i, iparent = NULL;
364 if (psplay_fast_prng()&1)
366 for (i = node->left; i->right; iparent = i, i = i->right);
368 iparent->right = i->left;
370 i->left = node->left;
371 i->right = node->right;
375 for (i = node->right; i->left; iparent = i, i = i->left);
377 iparent->left = i->right;
378 if (node->right != i)
379 i->right = node->right;
380 i->left = node->left;
385 if (self->elem_cnt < 1UL<<self->log2) --
self->log2;
421 if (res == PSPLAY_CONT)
424 if (res == PSPLAY_STOP)
426 else if (res == PSPLAY_REMOVE)
452 res = action (node, PSPLAY_PREORDER, level, data);
453 if (!psplay_handle (
self, node, res))
457 if (!
psplay_walk (
self, node->left, action, level+1, data))
460 res = action (node, PSPLAY_INORDER, level, data);
461 if (!psplay_handle (
self, node, res))
465 if (!
psplay_walk (
self, node->right, action, level+1, data))
468 res = action (node, PSPLAY_POSTORDER, level, data);
469 if (!psplay_handle (
self, node, res))
477 psplay_print_node (PSplaynode node,
const enum psplay_order_enum which,
int level,
void* data)
480 static char* sp =
" ";
483 if (which == PSPLAY_PREORDER)
484 fprintf (fh,
"%s ...\n", sp);
490 case PSPLAY_PREORDER:
491 fprintf (fh,
"%s%p\n", sp+40-level, node);
493 fprintf (fh,
"%sleft %p\n", sp+40-level, node->left);
497 fprintf (fh,
"%sright %p\n", sp+40-level, node->right);
499 case PSPLAY_POSTORDER:
507 psplay_dump (PSplay
self, FILE* dest)
509 fprintf (dest,
"root %p\n", self->tree);
510 psplay_walk (
self, NULL, psplay_print_node, 0, dest);
PSplay psplay_destroy(PSplay self)
Destroy a splay tree Frees all elements and associated resources of a splay tree. ...
psplay_delete_fn(* psplay_action_fn)(PSplaynode node, const enum psplay_order_enum which, int level, void *data)
Traverse a splay tree Traversing a tree calls a user supplied action three times An 'action' must not...
PSplay psplay_init(PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del)
Initialize a splay tree.
const void *(* psplay_key_fn)(const PSplaynode node)
Retrieve the key from a user datastructure.
This header is for including and configuring NoBug.
PSplaynode psplay_find(PSplay self, const void *key, int splayfactor)
Find a element in a splay tree.
PSplaynode psplay_insert(PSplay self, PSplaynode node, int splayfactor)
Insert a element into a splay tree.
void psplay_delete(PSplay self)
Delete a splay tree Frees all elements and associated resources of a splay tree and then itseld...
PSplay psplay_new(psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn del)
Allocate a splay tree.
Probabilistic splay tree.
int(* psplay_cmp_fn)(const void *a, const void *b)
Function use to compare keys.
PSplaynode psplay_remove(PSplay self, PSplaynode node)
Remove a node from a splay tree.
int psplay_walk(PSplay self, PSplaynode node, psplay_action_fn action, int level, void *data)
Start a tree traversal.
PSplaynode psplay_remove_key(PSplay self, void *key)
Remove a node by key from a splay tree.
void psplay_delete_key(PSplay self, void *key)
Delete a node by key from a splay tree.
PSplaynode psplaynode_init(PSplaynode self)
Initialise a splay tree node The user has to place this nodes within his datastructure and must Initi...
void(* psplay_delete_fn)(PSplaynode node)
Destructor for user defined data Called when an element got removed from a splay tree.
void psplay_delete_node(PSplay self, PSplaynode node)
Delete a node from a splay tree.