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