NEURON
sptree.h
Go to the documentation of this file.
1 /*
2 ** sptree.h: The following type declarations provide the binary tree
3 ** representation of event-sets or priority queues needed by splay trees
4 **
5 ** assumes that data and datb will be provided by the application
6 ** to hold all application specific information
7 **
8 ** assumes that key will be provided by the application, comparable
9 ** with the compare function applied to the addresses of two keys.
10 */
11 
12 #ifndef SPTREE_H
13 #define SPTREE_H
14 
15 #ifndef NULL
16 #define NULL 0
17 #endif
18 
19 #if 0
20 #define STRCMP(a, b) ((Sct = *(a) - *(b)) ? Sct : strcmp((a), (b)))
21 #else
22 #define STRCMP(a, b) (a - b)
23 #endif
24 
25 #if 0
26 typedef struct _spblk
27 {
28  struct _spblk * leftlink;
29  struct _spblk * rightlink;
30  struct _spblk * uplink;
31  int cnt;
32 
33  char * key; /* formerly time/timetyp */
34  char * data; /* formerly aux/auxtype */
35  char * datb;
36 } SPBLK;
37 #endif
38 
39 template <typename SPBLK>
40 struct SPTREE {
41  SPBLK* root; /* root node */
42 
43  /* Statistics, not strictly necessary, but handy for tuning */
44 
45  int lookups; /* number of splookup()s */
46  int lkpcmps; /* number of lookup comparisons */
47 
48  int enqs; /* number of spenq()s */
49  int enqcmps; /* compares in spenq */
50 
51  int splays;
53 };
54 
55 #define spinit sptq_spinit
56 #define spempty sptq_spempty
57 #define spenq sptq_spenq
58 #define spdeq sptq_spdeq
59 #define spenqprior sptq_spenqprior
60 #define splay sptq_splay
61 #define sphead sptq_sphead
62 #define spdelete sptq_spdelete
63 #define spnext sptq_spnext
64 #define spprev sptq_spprev
65 #define spenqbefore sptq_spenqbefore
66 #define spenqafter sptq_spenqafter
67 #define splookup sptq_splookup
68 /*#define spinstall sptq_spinstall*/
69 #define sptail sptq_sptail
70 #define spscan sptq_spscan
71 #define sprscan sptq_sprscan
72 #define spfhead sptq_spfhead
73 #define spfnext sptq_spfnext
74 #define spfprev sptq_spfprev
75 #define spstats sptq_spstats
76 
77 /* Original file: sptree.cpp
78  *
79  * sptree.cpp: The following code implements the basic operations on
80  * an event-set or priority-queue implemented using splay trees:
81  *
82 Hines changed to void spinit(SPTREE<SPBLK>**) for use with TQueue.
83  * SPTREE *spinit( compare ) Make a new tree
84  * int spempty(); Is tree empty?
85  * SPBLK *spenq( n, q ) Insert n in q after all equal keys.
86  * SPBLK *spdeq( np ) Return first key under *np, removing it.
87  * SPBLK *spenqprior( n, q ) Insert n in q before all equal keys.
88  * void splay( n, q ) n (already in q) becomes the root.
89  *
90  * In the above, n points to an SPBLK type, while q points to an
91  * SPTREE.
92  *
93  * The implementation used here is based on the implementation
94  * which was used in the tests of splay trees reported in:
95  *
96  * An Empirical Comparison of Priority-Queue and Event-Set Implementations,
97  * by Douglas W. Jones, Comm. ACM 29, 4 (Apr. 1986) 300-311.
98  *
99  * The changes made include the addition of the enqprior
100  * operation and the addition of up-links to allow for the splay
101  * operation. The basic splay tree algorithms were originally
102  * presented in:
103  *
104  * Self Adjusting Binary Trees,
105  * by D. D. Sleator and R. E. Tarjan,
106  * Proc. ACM SIGACT Symposium on Theory
107  * of Computing (Boston, Apr 1983) 235-245.
108  *
109  * The enq and enqprior routines use variations on the
110  * top-down splay operation, while the splay routine is bottom-up.
111  * All are coded for speed.
112  *
113  * Written by:
114  * Douglas W. Jones
115  *
116  * Translated to C by:
117  * David Brower, daveb@rtech.uucp
118  *
119  * Thu Oct 6 12:11:33 PDT 1988 (daveb) Fixed spdeq, which was broken
120  * handling one-node trees. I botched the pascal translation of
121  * a VAR parameter.
122  */
123 
124 
125 /* USER SUPPLIED! */
126 
127 /*extern char *emalloc();*/
128 
129 
130 /*----------------
131  *
132  * spinit() -- initialize an empty splay tree
133  *
134  */
135 template <typename SPBLK>
137  q->lookups = 0;
138  q->lkpcmps = 0;
139  q->enqs = 0;
140  q->enqcmps = 0;
141  q->splays = 0;
142  q->splayloops = 0;
143  q->root = NULL;
144 }
145 
146 /*----------------
147  *
148  * spempty() -- is an event-set represented as a splay tree empty?
149  */
150 template <typename SPBLK>
152  return (q == NULL || q->root == NULL);
153 }
154 
155 
156 /*----------------
157  *
158  * spenq() -- insert item in a tree.
159  *
160  * put n in q after all other nodes with the same key; when this is
161  * done, n will be the root of the splay tree representing q, all nodes
162  * in q with keys less than or equal to that of n will be in the
163  * left subtree, all with greater keys will be in the right subtree;
164  * the tree is split into these subtrees from the top down, with rotations
165  * performed along the way to shorten the left branch of the right subtree
166  * and the right branch of the left subtree
167  */
168 template <typename SPBLK>
169 SPBLK* spenq(SPBLK* n, SPTREE<SPBLK>* q) {
170  SPBLK* left; /* the rightmost node in the left tree */
171  SPBLK* right; /* the leftmost node in the right tree */
172  SPBLK* next; /* the root of the unsplit part */
173  SPBLK* temp;
174 
175  double key;
176  int Sct; /* Strcmp value */
177 
178  q->enqs++;
179  n->uplink = NULL;
180  next = q->root;
181  q->root = n;
182  if (next == NULL) /* trivial enq */
183  {
184  n->leftlink = NULL;
185  n->rightlink = NULL;
186  } else /* difficult enq */
187  {
188  key = n->key;
189  left = n;
190  right = n;
191 
192  /* n's left and right children will hold the right and left
193  splayed trees resulting from splitting on n->key;
194  note that the children will be reversed! */
195 
196  q->enqcmps++;
197  if (STRCMP(next->key, key) > 0)
198  goto two;
199 
200  one: /* assert next->key <= key */
201 
202  do /* walk to the right in the left tree */
203  {
204  temp = next->rightlink;
205  if (temp == NULL) {
206  left->rightlink = next;
207  next->uplink = left;
208  right->leftlink = NULL;
209  goto done; /* job done, entire tree split */
210  }
211 
212  q->enqcmps++;
213  if (STRCMP(temp->key, key) > 0) {
214  left->rightlink = next;
215  next->uplink = left;
216  left = next;
217  next = temp;
218  goto two; /* change sides */
219  }
220 
221  next->rightlink = temp->leftlink;
222  if (temp->leftlink != NULL)
223  temp->leftlink->uplink = next;
224  left->rightlink = temp;
225  temp->uplink = left;
226  temp->leftlink = next;
227  next->uplink = temp;
228  left = temp;
229  next = temp->rightlink;
230  if (next == NULL) {
231  right->leftlink = NULL;
232  goto done; /* job done, entire tree split */
233  }
234 
235  q->enqcmps++;
236 
237  } while (STRCMP(next->key, key) <= 0); /* change sides */
238 
239  two: /* assert next->key > key */
240 
241  do /* walk to the left in the right tree */
242  {
243  temp = next->leftlink;
244  if (temp == NULL) {
245  right->leftlink = next;
246  next->uplink = right;
247  left->rightlink = NULL;
248  goto done; /* job done, entire tree split */
249  }
250 
251  q->enqcmps++;
252  if (STRCMP(temp->key, key) <= 0) {
253  right->leftlink = next;
254  next->uplink = right;
255  right = next;
256  next = temp;
257  goto one; /* change sides */
258  }
259  next->leftlink = temp->rightlink;
260  if (temp->rightlink != NULL)
261  temp->rightlink->uplink = next;
262  right->leftlink = temp;
263  temp->uplink = right;
264  temp->rightlink = next;
265  next->uplink = temp;
266  right = temp;
267  next = temp->leftlink;
268  if (next == NULL) {
269  left->rightlink = NULL;
270  goto done; /* job done, entire tree split */
271  }
272 
273  q->enqcmps++;
274 
275  } while (STRCMP(next->key, key) > 0); /* change sides */
276 
277  goto one;
278 
279  done: /* split is done, branches of n need reversal */
280 
281  temp = n->leftlink;
282  n->leftlink = n->rightlink;
283  n->rightlink = temp;
284  }
285 
286 #if BBTQ != 4 && BBTQ != 5
287  n->cnt++;
288 #endif
289  return (n);
290 
291 } /* spenq */
292 
293 
294 /*----------------
295  *
296  * spdeq() -- return and remove head node from a subtree.
297  *
298  * remove and return the head node from the node set; this deletes
299  * (and returns) the leftmost node from q, replacing it with its right
300  * subtree (if there is one); on the way to the leftmost node, rotations
301  * are performed to shorten the left branch of the tree
302  */
303 template <typename SPBLK>
304 SPBLK* spdeq(SPBLK** np) /* pointer to a node pointer */
305 
306 {
307  SPBLK* deq; /* one to return */
308  SPBLK* next; /* the next thing to deal with */
309  SPBLK* left; /* the left child of next */
310  SPBLK* farleft; /* the left child of left */
311  SPBLK* farfarleft; /* the left child of farleft */
312 
313  if (np == NULL || *np == NULL) {
314  deq = NULL;
315  } else {
316  next = *np;
317  left = next->leftlink;
318  if (left == NULL) {
319  deq = next;
320  *np = next->rightlink;
321 
322  if (*np != NULL)
323  (*np)->uplink = NULL;
324 
325  } else
326  for (;;) /* left is not null */
327  {
328  /* next is not it, left is not NULL, might be it */
329  farleft = left->leftlink;
330  if (farleft == NULL) {
331  deq = left;
332  next->leftlink = left->rightlink;
333  if (left->rightlink != NULL)
334  left->rightlink->uplink = next;
335  break;
336  }
337 
338  /* next, left are not it, farleft is not NULL, might be it */
339  farfarleft = farleft->leftlink;
340  if (farfarleft == NULL) {
341  deq = farleft;
342  left->leftlink = farleft->rightlink;
343  if (farleft->rightlink != NULL)
344  farleft->rightlink->uplink = left;
345  break;
346  }
347 
348  /* next, left, farleft are not it, rotate */
349  next->leftlink = farleft;
350  farleft->uplink = next;
351  left->leftlink = farleft->rightlink;
352  if (farleft->rightlink != NULL)
353  farleft->rightlink->uplink = left;
354  farleft->rightlink = left;
355  left->uplink = farleft;
356  next = farleft;
357  left = farfarleft;
358  }
359  }
360 
361  return (deq);
362 
363 } /* spdeq */
364 
365 
366 /*----------------
367  *
368  * spenqprior() -- insert into tree before other equal keys.
369  *
370  * put n in q before all other nodes with the same key; after this is
371  * done, n will be the root of the splay tree representing q, all nodes in
372  * q with keys less than that of n will be in the left subtree, all with
373  * greater or equal keys will be in the right subtree; the tree is split
374  * into these subtrees from the top down, with rotations performed along
375  * the way to shorten the left branch of the right subtree and the right
376  * branch of the left subtree; the logic of spenqprior is exactly the
377  * same as that of spenq except for a substitution of comparison
378  * operators
379  */
380 template <typename SPBLK>
381 SPBLK* spenqprior(SPBLK* n, SPTREE<SPBLK>* q) {
382  SPBLK* left; /* the rightmost node in the left tree */
383  SPBLK* right; /* the leftmost node in the right tree */
384  SPBLK* next; /* the root of unsplit part of tree */
385  SPBLK* temp;
386  int Sct; /* Strcmp value */
387  double key;
388 
389  n->uplink = NULL;
390  next = q->root;
391  q->root = n;
392  if (next == NULL) /* trivial enq */
393  {
394  n->leftlink = NULL;
395  n->rightlink = NULL;
396  } else /* difficult enq */
397  {
398  key = n->key;
399  left = n;
400  right = n;
401 
402  /* n's left and right children will hold the right and left
403  splayed trees resulting from splitting on n->key;
404  note that the children will be reversed! */
405 
406  if (STRCMP(next->key, key) >= 0)
407  goto two;
408 
409  one: /* assert next->key < key */
410 
411  do /* walk to the right in the left tree */
412  {
413  temp = next->rightlink;
414  if (temp == NULL) {
415  left->rightlink = next;
416  next->uplink = left;
417  right->leftlink = NULL;
418  goto done; /* job done, entire tree split */
419  }
420  if (STRCMP(temp->key, key) >= 0) {
421  left->rightlink = next;
422  next->uplink = left;
423  left = next;
424  next = temp;
425  goto two; /* change sides */
426  }
427  next->rightlink = temp->leftlink;
428  if (temp->leftlink != NULL)
429  temp->leftlink->uplink = next;
430  left->rightlink = temp;
431  temp->uplink = left;
432  temp->leftlink = next;
433  next->uplink = temp;
434  left = temp;
435  next = temp->rightlink;
436  if (next == NULL) {
437  right->leftlink = NULL;
438  goto done; /* job done, entire tree split */
439  }
440 
441  } while (STRCMP(next->key, key) < 0); /* change sides */
442 
443  two: /* assert next->key >= key */
444 
445  do /* walk to the left in the right tree */
446  {
447  temp = next->leftlink;
448  if (temp == NULL) {
449  right->leftlink = next;
450  next->uplink = right;
451  left->rightlink = NULL;
452  goto done; /* job done, entire tree split */
453  }
454  if (STRCMP(temp->key, key) < 0) {
455  right->leftlink = next;
456  next->uplink = right;
457  right = next;
458  next = temp;
459  goto one; /* change sides */
460  }
461  next->leftlink = temp->rightlink;
462  if (temp->rightlink != NULL)
463  temp->rightlink->uplink = next;
464  right->leftlink = temp;
465  temp->uplink = right;
466  temp->rightlink = next;
467  next->uplink = temp;
468  right = temp;
469  next = temp->leftlink;
470  if (next == NULL) {
471  left->rightlink = NULL;
472  goto done; /* job done, entire tree split */
473  }
474 
475  } while (STRCMP(next->key, key) >= 0); /* change sides */
476 
477  goto one;
478 
479  done: /* split is done, branches of n need reversal */
480 
481  temp = n->leftlink;
482  n->leftlink = n->rightlink;
483  n->rightlink = temp;
484  }
485 
486  return (n);
487 
488 } /* spenqprior */
489 
490 /*----------------
491  *
492  * splay() -- reorganize the tree.
493  *
494  * the tree is reorganized so that n is the root of the
495  * splay tree representing q; results are unpredictable if n is not
496  * in q to start with; q is split from n up to the old root, with all
497  * nodes to the left of n ending up in the left subtree, and all nodes
498  * to the right of n ending up in the right subtree; the left branch of
499  * the right subtree and the right branch of the left subtree are
500  * shortened in the process
501  *
502  * this code assumes that n is not NULL and is in q; it can sometimes
503  * detect n not in q and complain
504  */
505 
506 template <typename SPBLK>
507 void splay(SPBLK* n, SPTREE<SPBLK>* q) {
508  SPBLK* up; /* points to the node being dealt with */
509  SPBLK* prev; /* a descendent of up, already dealt with */
510  SPBLK* upup; /* the parent of up */
511  SPBLK* upupup; /* the grandparent of up */
512  SPBLK* left; /* the top of left subtree being built */
513  SPBLK* right; /* the top of right subtree being built */
514 
515 #if BBTQ != 4 && BBTQ != 5
516  n->cnt++; /* bump reference count */
517 #endif
518 
519  left = n->leftlink;
520  right = n->rightlink;
521  prev = n;
522  up = prev->uplink;
523 
524  q->splays++;
525 
526  while (up != NULL) {
527  q->splayloops++;
528 
529  /* walk up the tree towards the root, splaying all to the left of
530  n into the left subtree, all to right into the right subtree */
531 
532  upup = up->uplink;
533  if (up->leftlink == prev) /* up is to the right of n */
534  {
535  if (upup != NULL && upup->leftlink == up) /* rotate */
536  {
537  upupup = upup->uplink;
538  upup->leftlink = up->rightlink;
539  if (upup->leftlink != NULL)
540  upup->leftlink->uplink = upup;
541  up->rightlink = upup;
542  upup->uplink = up;
543  if (upupup == NULL)
544  q->root = up;
545  else if (upupup->leftlink == upup)
546  upupup->leftlink = up;
547  else
548  upupup->rightlink = up;
549  up->uplink = upupup;
550  upup = upupup;
551  }
552  up->leftlink = right;
553  if (right != NULL)
554  right->uplink = up;
555  right = up;
556 
557  } else /* up is to the left of n */
558  {
559  if (upup != NULL && upup->rightlink == up) /* rotate */
560  {
561  upupup = upup->uplink;
562  upup->rightlink = up->leftlink;
563  if (upup->rightlink != NULL)
564  upup->rightlink->uplink = upup;
565  up->leftlink = upup;
566  upup->uplink = up;
567  if (upupup == NULL)
568  q->root = up;
569  else if (upupup->rightlink == upup)
570  upupup->rightlink = up;
571  else
572  upupup->leftlink = up;
573  up->uplink = upupup;
574  upup = upupup;
575  }
576  up->rightlink = left;
577  if (left != NULL)
578  left->uplink = up;
579  left = up;
580  }
581  prev = up;
582  up = upup;
583  }
584 
585 #ifdef DEBUG
586  if (q->root != prev) {
587  /* fprintf(stderr, " *** bug in splay: n not in q *** " ); */
588  abort();
589  }
590 #endif
591 
592  n->leftlink = left;
593  n->rightlink = right;
594  if (left != NULL)
595  left->uplink = n;
596  if (right != NULL)
597  right->uplink = n;
598  q->root = n;
599  n->uplink = NULL;
600 
601 } /* splay */
602 
603 
604 /* Original file: spaux.cpp
605 
606  spaux.cpp: This code implements the following operations on an event-set
607  or priority-queue implemented using splay trees:
608 
609  n = sphead( q ) n is the head item in q (not removed).
610  spdelete( n, q ) n is removed from q.
611  n = spnext( np, q ) n is the successor of np in q.
612  n = spprev( np, q ) n is the predecessor of np in q.
613  spenqbefore( n, np, q ) n becomes the predecessor of np in q.
614  spenqafter( n, np, q ) n becomes the successor of np in q.
615 
616  In the above, n and np are pointers to single items (type
617  SPBLK *); q is an event-set (type SPTREE *),
618  The type definitions for these are taken
619  from file sptree.h. All of these operations rest on basic
620  splay tree operations from file sptree.cpp.
621 
622  The basic splay tree algorithms were originally presented in:
623 
624  Self Adjusting Binary Trees,
625  by D. D. Sleator and R. E. Tarjan,
626  Proc. ACM SIGACT Symposium on Theory
627  of Computing (Boston, Apr 1983) 235-245.
628 
629  The operations in this package supplement the operations from
630  file splay.h to provide support for operations typically needed
631  on the pending event set in discrete event simulation. See, for
632  example,
633 
634  Introduction to Simula 67,
635  by Gunther Lamprecht, Vieweg & Sohn, Braucschweig, Wiesbaden, 1981.
636  (Chapter 14 contains the relevant discussion.)
637 
638  Simula Begin,
639  by Graham M. Birtwistle, et al, Studentlitteratur, Lund, 1979.
640  (Chapter 9 contains the relevant discussion.)
641 
642  Many of the routines in this package use the splay procedure,
643  for bottom-up splaying of the queue. Consequently, item n in
644  delete and item np in all operations listed above must be in the
645  event-set prior to the call or the results will be
646  unpredictable (eg: chaos will ensue).
647 
648  Note that, in all cases, these operations can be replaced with
649  the corresponding operations formulated for a conventional
650  lexicographically ordered tree. The versions here all use the
651  splay operation to ensure the amortized bounds; this usually
652  leads to a very compact formulation of the operations
653  themselves, but it may slow the average performance.
654 
655  Alternative versions based on simple binary tree operations are
656  provided (commented out) for head, next, and prev, since these
657  are frequently used to traverse the entire data structure, and
658  the cost of traversal is independent of the shape of the
659  structure, so the extra time taken by splay in this context is
660  wasted.
661 
662  This code was written by:
663  Douglas W. Jones with assistance from Srinivas R. Sataluri
664 
665  Translated to C by David Brower, daveb@rtech.uucp
666 
667  Thu Oct 6 12:11:33 PDT 1988 (daveb) Fixed spdeq, which was broken
668  handling one-node trees. I botched the pascal translation of
669  a VAR parameter. Changed interface, so callers must also be
670  corrected to pass the node by address rather than value.
671  Mon Apr 3 15:18:32 PDT 1989 (daveb)
672  Apply fix supplied by Mark Moraes <moraes@csri.toronto.edu> to
673  spdelete(), which dropped core when taking out the last element
674  in a subtree -- that is, when the right subtree was empty and
675  the leftlink was also null, it tried to take out the leftlink's
676  uplink anyway.
677  */
678 
679 /*----------------
680  *
681  * sphead() -- return the "lowest" element in the tree.
682  *
683  * returns a reference to the head event in the event-set q,
684  * represented as a splay tree; q->root ends up pointing to the head
685  * event, and the old left branch of q is shortened, as if q had
686  * been splayed about the head element; this is done by dequeueing
687  * the head and then making the resulting queue the right son of
688  * the head returned by spdeq; an alternative is provided which
689  * avoids splaying but just searches for and returns a pointer to
690  * the bottom of the left branch
691  */
692 template <typename SPBLK>
694  SPBLK* x;
695 
696  /* splay version, good amortized bound */
697  x = spdeq(&q->root);
698  if (x != NULL) {
699  x->rightlink = q->root;
700  x->leftlink = NULL;
701  x->uplink = NULL;
702  if (q->root != NULL)
703  q->root->uplink = x;
704  }
705  q->root = x;
706 
707  /* alternative version, bad amortized bound,
708  but faster on the average */
709 
710 #if 0
711  x = q->root;
712  while( x->leftlink != NULL )
713  x = x->leftlink;
714 #endif
715 
716  return (x);
717 
718 } /* sphead */
719 
720 
721 /*----------------
722  *
723  * spdelete() -- Delete node from a tree.
724  *
725  * n is deleted from q; the resulting splay tree has been splayed
726  * around its new root, which is the successor of n
727  *
728  */
729 template <typename SPBLK>
730 void spdelete(SPBLK* n, SPTREE<SPBLK>* q) {
731  SPBLK* x;
732 
733  splay(n, q);
734  x = spdeq(&q->root->rightlink);
735  if (x == NULL) /* empty right subtree */
736  {
737  q->root = q->root->leftlink;
738  if (q->root)
739  q->root->uplink = NULL;
740  } else /* non-empty right subtree */
741  {
742  x->uplink = NULL;
743  x->leftlink = q->root->leftlink;
744  x->rightlink = q->root->rightlink;
745  if (x->leftlink != NULL)
746  x->leftlink->uplink = x;
747  if (x->rightlink != NULL)
748  x->rightlink->uplink = x;
749  q->root = x;
750  }
751 
752 } /* spdelete */
753 
754 
755 /*----------------
756  *
757  * spnext() -- return next higer item in the tree, or NULL.
758  *
759  * return the successor of n in q, represented as a splay tree; the
760  * successor becomes the root; two alternate versions are provided,
761  * one which is shorter, but slower, and one which is faster on the
762  * average because it does not do any splaying
763  *
764  */
765 template <typename SPBLK>
766 SPBLK* spnext(SPBLK* n, SPTREE<SPBLK>* q) {
767  SPBLK* next;
768  SPBLK* x;
769 
770  /* splay version */
771  splay(n, q);
772  x = spdeq(&n->rightlink);
773  if (x != NULL) {
774  x->leftlink = n;
775  n->uplink = x;
776  x->rightlink = n->rightlink;
777  n->rightlink = NULL;
778  if (x->rightlink != NULL)
779  x->rightlink->uplink = x;
780  q->root = x;
781  x->uplink = NULL;
782  }
783  next = x;
784 
785  /* shorter slower version;
786  deleting last "if" undoes the amortized bound */
787 
788 #if 0
789  splay( n, q );
790  x = n->rightlink;
791  if( x != NULL )
792  while( x->leftlink != NULL )
793  x = x->leftlink;
794  next = x;
795  if( x != NULL )
796  splay( x, q );
797 #endif
798 
799  return (next);
800 
801 } /* spnext */
802 
803 
804 /*----------------
805  *
806  * spprev() -- return previous node in a tree, or NULL.
807  *
808  * return the predecessor of n in q, represented as a splay tree;
809  * the predecessor becomes the root; an alternate version is
810  * provided which is faster on the average because it does not do
811  * any splaying
812  *
813  */
814 template <typename SPBLK>
815 SPBLK* spprev(SPBLK* n, SPTREE<SPBLK>* q) {
816  SPBLK* prev;
817  SPBLK* x;
818 
819  /* splay version;
820  note: deleting the last "if" undoes the amortized bound */
821 
822  splay(n, q);
823  x = n->leftlink;
824  if (x != NULL)
825  while (x->rightlink != NULL)
826  x = x->rightlink;
827  prev = x;
828  if (x != NULL)
829  splay(x, q);
830 
831  return (prev);
832 
833 } /* spprev */
834 
835 
836 /*----------------
837  *
838  * spenqbefore() -- insert node before another in a tree.
839  *
840  * returns pointer to n.
841  *
842  * event n is entered in the splay tree q as the immediate
843  * predecessor of n1; in doing so, n1 becomes the root of the tree
844  * with n as its left son
845  *
846  */
847 template <typename SPBLK>
848 SPBLK* spenqbefore(SPBLK* n, SPBLK* n1, SPTREE<SPBLK>* q) {
849  splay(n1, q);
850  n->key = n1->key;
851  n->leftlink = n1->leftlink;
852  if (n->leftlink != NULL)
853  n->leftlink->uplink = n;
854  n->rightlink = NULL;
855  n->uplink = n1;
856  n1->leftlink = n;
857 
858  return (n);
859 
860 } /* spenqbefore */
861 
862 
863 /*----------------
864  *
865  * spenqafter() -- enter n after n1 in tree q.
866  *
867  * returns a pointer to n.
868  *
869  * event n is entered in the splay tree q as the immediate
870  * successor of n1; in doing so, n1 becomes the root of the tree
871  * with n as its right son
872  */
873 template <typename SPBLK>
874 SPBLK* spenqafter(SPBLK* n, SPBLK* n1, SPTREE<SPBLK>* q) {
875  splay(n1, q);
876  n->key = n1->key;
877  n->rightlink = n1->rightlink;
878  if (n->rightlink != NULL)
879  n->rightlink->uplink = n;
880  n->leftlink = NULL;
881  n->uplink = n1;
882  n1->rightlink = n;
883 
884  return (n);
885 
886 } /* spenqafter */
887 
888 
889 /* Original file: spdaveb.cpp
890  *
891  * spdaveb.cpp -- daveb's new splay tree functions.
892  *
893  * The functions in this file provide an interface that is nearly
894  * the same as the hash library I swiped from mkmf, allowing
895  * replacement of one by the other. Hey, it worked for me!
896  *
897  * splookup() -- given a key, find a node in a tree.
898  * spinstall() -- install an item in the tree, overwriting existing value.
899  * spfhead() -- fast (non-splay) find the first node in a tree.
900  * spftail() -- fast (non-splay) find the last node in a tree.
901  * spscan() -- forward scan tree from the head.
902  * sprscan() -- reverse scan tree from the tail.
903  * spfnext() -- non-splaying next.
904  * spfprev() -- non-splaying prev.
905  * spstats() -- make char string of stats for a tree.
906  *
907  * Written by David Brower, daveb@rtech.uucp 1/88.
908  */
909 
910 
911 /*----------------
912  *
913  * splookup() -- given key, find a node in a tree.
914  *
915  * Splays the found node to the root.
916  */
917 template <typename SPBLK>
918 SPBLK* splookup(double key, SPTREE<SPBLK>* q) {
919  SPBLK* n;
920  int Sct;
921  int c;
922 
923  /* find node in the tree */
924  n = q->root;
925  c = ++(q->lkpcmps);
926  q->lookups++;
927  // while( n && (Sct = STRCMP( key, n->key ) ) )
928  while (n && (Sct = key != n->key)) {
929  c++;
930  n = (Sct < 0) ? n->leftlink : n->rightlink;
931  }
932  q->lkpcmps = c;
933 
934  /* reorganize tree around this node */
935  if (n != NULL)
936  splay(n, q);
937 
938  return (n);
939 }
940 
941 
942 #if 0
943 
944 /*----------------
945  *
946  * spinstall() -- install an entry in a tree, overwriting any existing node.
947  *
948  * If the node already exists, replace its contents.
949  * If it does not exist, then allocate a new node and fill it in.
950  */
951 
952 SPBLK *
953 spinstall( key, data, datb, q )
954 
955 char * key;
956 char * data;
957 char * datb;
958 SPTREE *q;
959 
960 {
961  SPBLK *n;
962 
963  if( NULL == ( n = splookup( key, q ) ) )
964  {
965  n = (SPBLK *) emalloc( sizeof( *n ) );
966  n->key = key;
967  n->leftlink = NULL;
968  n->rightlink = NULL;
969  n->uplink = NULL;
970 #if BBTQ != 4 && BBTQ != 5
971  n->cnt = 0;
972 #endif
973  spenq( n, q );
974  }
975 
976  n->data = data;
977  n->datb = datb;
978 
979  return( n );
980 }
981 #endif
982 
983 
984 /*----------------
985  *
986  * spfhead() -- return the "lowest" element in the tree.
987  *
988  * returns a reference to the head event in the event-set q.
989  * avoids splaying but just searches for and returns a pointer to
990  * the bottom of the left branch.
991  */
992 template <typename SPBLK>
994  SPBLK* x;
995 
996  if (NULL != (x = q->root))
997  while (x->leftlink != NULL)
998  x = x->leftlink;
999 
1000  return (x);
1001 
1002 } /* spfhead */
1003 
1004 
1005 /*----------------
1006  *
1007  * spftail() -- find the last node in a tree.
1008  *
1009  * Fast version does not splay result or intermediate steps.
1010  */
1011 template <typename SPBLK>
1013  SPBLK* x;
1014 
1015 
1016  if (NULL != (x = q->root))
1017  while (x->rightlink != NULL)
1018  x = x->rightlink;
1019 
1020  return (x);
1021 
1022 } /* spftail */
1023 
1024 
1025 /*----------------
1026  *
1027  * spscan() -- apply a function to nodes in ascending order.
1028  *
1029  * if n is given, start at that node, otherwise start from
1030  * the head.
1031  */
1032 class TQItem;
1033 
1034 template <typename SPBLK>
1035 void spscan(void (*f)(const SPBLK*, int), SPBLK* n, SPTREE<SPBLK>* q) {
1036  SPBLK* x;
1037 
1038  for (x = n != NULL ? n : spfhead<SPBLK>(q); x != NULL; x = spfnext(x))
1039  (*f)(x, 0);
1040 }
1041 
1042 
1043 /*----------------
1044  *
1045  * sprscan() -- apply a function to nodes in descending order.
1046  *
1047  * if n is given, start at that node, otherwise start from
1048  * the tail.
1049  */
1050 template <typename SPBLK>
1051 void sprscan(void (*f)(const TQItem*, int), SPBLK* n, SPTREE<SPBLK>* q) {
1052  SPBLK* x;
1053 
1054  for (x = n != NULL ? n : spftail<SPBLK>(q); x != NULL; x = spfprev(x))
1055  (*f)(x, 0);
1056 }
1057 
1058 
1059 /*----------------
1060  *
1061  * spfnext() -- fast return next higer item in the tree, or NULL.
1062  *
1063  * return the successor of n in q, represented as a splay tree.
1064  * This is a fast (on average) version that does not splay.
1065  */
1066 template <typename SPBLK>
1067 SPBLK* spfnext(SPBLK* n) {
1068  SPBLK* next;
1069  SPBLK* x;
1070 
1071  /* a long version, avoids splaying for fast average,
1072  * poor amortized bound
1073  */
1074 
1075  if (n == NULL)
1076  return (n);
1077 
1078  x = n->rightlink;
1079  if (x != NULL) {
1080  while (x->leftlink != NULL)
1081  x = x->leftlink;
1082  next = x;
1083  } else /* x == NULL */
1084  {
1085  x = n->uplink;
1086  next = NULL;
1087  while (x != NULL) {
1088  if (x->leftlink == n) {
1089  next = x;
1090  x = NULL;
1091  } else {
1092  n = x;
1093  x = n->uplink;
1094  }
1095  }
1096  }
1097 
1098  return (next);
1099 
1100 } /* spfnext */
1101 
1102 
1103 /*----------------
1104  *
1105  * spfprev() -- return fast previous node in a tree, or NULL.
1106  *
1107  * return the predecessor of n in q, represented as a splay tree.
1108  * This is a fast (on average) version that does not splay.
1109  */
1110 template <typename SPBLK>
1111 SPBLK* spfprev(SPBLK* n) {
1112  SPBLK* prev;
1113  SPBLK* x;
1114 
1115  /* a long version,
1116  * avoids splaying for fast average, poor amortized bound
1117  */
1118 
1119  if (n == NULL)
1120  return (n);
1121 
1122  x = n->leftlink;
1123  if (x != NULL) {
1124  while (x->rightlink != NULL)
1125  x = x->rightlink;
1126  prev = x;
1127  } else {
1128  x = n->uplink;
1129  prev = NULL;
1130  while (x != NULL) {
1131  if (x->rightlink == n) {
1132  prev = x;
1133  x = NULL;
1134  } else {
1135  n = x;
1136  x = n->uplink;
1137  }
1138  }
1139  }
1140 
1141  return (prev);
1142 
1143 } /* spfprev */
1144 
1145 
1146 template <typename SPBLK>
1147 const char* spstats(SPTREE<SPBLK>* q) {
1148  static char buf[128];
1149  float llen;
1150  float elen;
1151  float sloops;
1152 
1153  if (q == NULL)
1154  return ("");
1155 
1156  llen = q->lookups ? (float) q->lkpcmps / q->lookups : 0;
1157  elen = q->enqs ? (float) q->enqcmps / q->enqs : 0;
1158  sloops = q->splays ? (float) q->splayloops / q->splays : 0;
1159 
1160  sprintf(buf,
1161  "f(%d %4.2f) i(%d %4.2f) s(%d %4.2f)",
1162  q->lookups,
1163  llen,
1164  q->enqs,
1165  elen,
1166  q->splays,
1167  sloops);
1168 
1169  return (const char*) buf;
1170 }
1171 
1172 
1173 #endif
Definition: bbtqueue.h:6
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
#define c
char buf[512]
Definition: init.cpp:13
Item * prev(Item *item)
Definition: list.cpp:93
char * emalloc(unsigned n)
Definition: list.cpp:166
Item * next(Item *item)
Definition: list.cpp:88
int const size_t const size_t n
Definition: nrngsl.h:11
size_t q
static double done(void *v)
Definition: ocbbs.cpp:282
#define left
Definition: rbtqueue.cpp:45
#define data
Definition: rbtqueue.cpp:49
#define right
Definition: rbtqueue.cpp:46
#define uplink
Definition: spt2queue.cpp:18
#define cnt
Definition: spt2queue.cpp:19
#define leftlink
Definition: spt2queue.cpp:16
#define rightlink
Definition: spt2queue.cpp:17
#define key
Definition: spt2queue.cpp:20
#define spnext
Definition: sptree.h:63
#define spfprev
Definition: sptree.h:74
#define NULL
Definition: sptree.h:16
#define sprscan
Definition: sptree.h:71
#define sphead
Definition: sptree.h:61
#define spfnext
Definition: sptree.h:73
#define spenq
Definition: sptree.h:57
#define STRCMP(a, b)
Definition: sptree.h:22
#define spfhead
Definition: sptree.h:72
#define spinit
Definition: sptree.h:55
#define spenqafter
Definition: sptree.h:66
#define splookup
Definition: sptree.h:67
#define spenqprior
Definition: sptree.h:59
#define spscan
Definition: sptree.h:70
#define spdeq
Definition: sptree.h:58
#define spenqbefore
Definition: sptree.h:65
#define splay
Definition: sptree.h:60
SPBLK * spftail(SPTREE< SPBLK > *q)
Definition: sptree.h:1012
#define spempty
Definition: sptree.h:56
#define spdelete
Definition: sptree.h:62
#define spprev
Definition: sptree.h:64
#define spstats
Definition: sptree.h:75
Definition: sptree.h:40
int enqs
Definition: sptree.h:48
int enqcmps
Definition: sptree.h:49
int splayloops
Definition: sptree.h:52
int lkpcmps
Definition: sptree.h:46
int lookups
Definition: sptree.h:45
int splays
Definition: sptree.h:51
SPBLK * root
Definition: sptree.h:41