39 #ifndef PSPLAY_TRAIL_DEPTH 40 #define PSPLAY_TRAIL_DEPTH 128 55 #define PSPLAY_FORMULA (self->log2*100/(depth + (psplay_fast_prng () & 63)) + trail->dir) * splayfactor 57 #ifndef PSPLAY_PROB_ZIGZIG 58 #define PSPLAY_PROB_ZIGZIG 5000 60 #ifndef PSPLAY_PROB_ZIGZAG 61 #define PSPLAY_PROB_ZIGZAG 2500 67 static inline uint32_t psplay_fast_prng ()
69 static uint32_t rnd=0xbabeface;
70 return rnd = rnd<<1 ^ ((rnd >> 30) & 1) ^ ((rnd>>2) & 1);
85 self->found_parent = &
self->tree;
99 PSplay
self = malloc (
sizeof *
self);
113 if (
self)
while (self->tree)
134 self->left =
self->right = NULL;
155 PSplaynode* trail[PSPLAY_TRAIL_DEPTH];
158 static inline unsigned 159 trailidx (
unsigned n)
161 return n & (PSPLAY_TRAIL_DEPTH-1);
166 psplay_splay (PSplay
self,
struct psplaytrail* trail,
unsigned splayfactor)
168 TRACE (psplay_dbg,
"%p %u",
self, splayfactor);
170 if (trail->dir < 0) trail->dir = - trail->dir;
172 for (
unsigned lim = PSPLAY_TRAIL_DEPTH, depth = trail->depth; lim > 2 && depth > 2; lim-=2, depth-=2)
174 PSplaynode node = *trail->trail [trailidx (depth)];
175 PSplaynode parent = *trail->trail [trailidx (depth-1)];
176 PSplaynode grandparent = *trail->trail [trailidx (depth-2)];
178 unsigned r = PSPLAY_FORMULA;
179 TRACE (psplay_dbg,
"r is %u", r);
181 if (parent == grandparent->left)
183 TRACE (psplay_dbg,
"ZIG..");
184 if (node == parent->left)
186 TRACE (psplay_dbg,
"..ZIG");
187 if (r < PSPLAY_PROB_ZIGZIG)
189 TRACE (psplay_dbg,
"BREAK");
193 grandparent->left = parent->right;
194 parent->right = grandparent;
196 parent->left = node->right;
197 node->right = parent;
201 TRACE (psplay_dbg,
"..ZAG");
202 if (r < PSPLAY_PROB_ZIGZAG)
204 TRACE (psplay_dbg,
"BREAK");
208 parent->right = node->left;
211 grandparent->left = node->right;
212 node->right = grandparent;
217 TRACE (psplay_dbg,
"ZAG..");
218 if (node == parent->left)
220 TRACE (psplay_dbg,
"..ZIG");
221 if (r < PSPLAY_PROB_ZIGZAG)
223 TRACE (psplay_dbg,
"BREAK");
227 parent->left = node->right;
228 node->right = parent;
230 grandparent->right = node->left;
231 node->left = grandparent;
235 TRACE (psplay_dbg,
"..ZAG");
236 if (r < PSPLAY_PROB_ZIGZIG)
238 TRACE (psplay_dbg,
"BREAK");
242 grandparent->right = parent->left;
243 parent->left = grandparent;
245 parent->right = node->left;
249 *trail->trail [trailidx (depth-2)] = node;
258 PSplaynode n =
self->tree;
263 trail.trail [0] = &
self->tree;
272 c =
self->cmp (self->key (node),
self->key (n));
280 trail.trail [trailidx (trail.depth)] = &n->left;
288 trail.trail [trailidx (trail.depth)] = &n->right;
293 WARN (psplay_dbg,
"dropping duplicate entry for psplay");
300 if (self->elem_cnt >= 1UL<<self->log2) ++
self->log2;
301 if (splayfactor && trail.depth > 2)
302 psplay_splay (
self, &trail, splayfactor);
312 PSplaynode node =
self->tree;
316 trail.trail [0] = &
self->tree;
321 c =
self->cmp (key, self->key (node));
327 trail.trail [trailidx (trail.depth)] = &node->left;
333 trail.trail [trailidx (trail.depth)] = &node->right;
338 self->found_parent = trail.trail [trailidx (--trail.depth)];
342 if (node && splayfactor && trail.depth > 2)
343 psplay_splay (
self, &trail, splayfactor);
352 if (!node)
return NULL;
354 PSplaynode* r =
self->found_parent;
360 WARN (psplay_dbg,
"node %p is not in splay tree %p", node,
self);
363 r =
self->found_parent;
368 else if (!node->right)
372 PSplaynode i, iparent = NULL;
373 if (psplay_fast_prng()&1)
375 for (i = node->left; i->right; iparent = i, i = i->right);
377 iparent->right = i->left;
379 i->left = node->left;
380 i->right = node->right;
384 for (i = node->right; i->left; iparent = i, i = i->left);
386 iparent->left = i->right;
387 if (node->right != i)
388 i->right = node->right;
389 i->left = node->left;
394 if (self->elem_cnt < 1UL<<self->log2) --
self->log2;
430 if (res == PSPLAY_CONT)
433 if (res == PSPLAY_STOP)
435 else if (res == PSPLAY_REMOVE)
461 res = action (node, PSPLAY_PREORDER, level, data);
462 if (!psplay_handle (
self, node, res))
466 if (!
psplay_walk (
self, node->left, action, level+1, data))
469 res = action (node, PSPLAY_INORDER, level, data);
470 if (!psplay_handle (
self, node, res))
474 if (!
psplay_walk (
self, node->right, action, level+1, data))
477 res = action (node, PSPLAY_POSTORDER, level, data);
478 if (!psplay_handle (
self, node, res))
486 psplay_print_node (PSplaynode node,
const enum psplay_order_enum which,
int level,
void* data)
489 static char* sp =
" ";
492 if (which == PSPLAY_PREORDER)
493 fprintf (fh,
"%s ...\n", sp);
499 case PSPLAY_PREORDER:
500 fprintf (fh,
"%s%p\n", sp+40-level, node);
502 fprintf (fh,
"%sleft %p\n", sp+40-level, node->left);
506 fprintf (fh,
"%sright %p\n", sp+40-level, node->right);
508 case PSPLAY_POSTORDER:
516 psplay_dump (PSplay
self, FILE* dest)
518 fprintf (dest,
"root %p\n", self->tree);
519 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.