SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
BinaryTree.java
1/*
2 * Class: BinaryTree
3 * Description: implementation of class EventList using a binary search tree
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.simevents.eventlist;
26
27import java.util.Iterator;
28import java.util.ListIterator;
29import java.util.ConcurrentModificationException;
30import java.util.NoSuchElementException;
31import umontreal.ssj.simevents.Event;
32import umontreal.ssj.util.PrintfFormat;
33
50public class BinaryTree implements EventList {
51 // racine de l'arbre
52 private Entry root = null;
53
54 // compteur de modifications sur l'iterateur.
55 private int modCount = 0;
56
57 public boolean isEmpty() {
58 return root == null;
59 }
60
61 public void clear() {
62 while (root != null)
63 remove(root);
64 }
65
66 public void add(Event ev) {
67 // fonction qui ajoute un evenement dans l'arbre
68 // note : si deux evenements ont le meme temps, alors il faut
69 // toujours faire en sorte que ces evenements se retrouvent
70 // comme les fils droits les uns des autres
71
72 Entry cursor = root;
73 boolean found = false;
74
75 if (cursor == null)
76 root = add(ev, null);
77 else {
78 while (!found) {
79 if (ev.compareTo(cursor.event) < 0) {
80 if (cursor.left == null) {
81 cursor.left = add(ev, cursor);
82 found = true;
83 }
84 cursor = cursor.left;
85
86 } else {
87 if (cursor.right == null) {
88 cursor.right = add(ev, cursor);
89 found = true;
90 }
91 cursor = cursor.right;
92 }
93 }
94 }
95 ++modCount;
96 }
97
98 public void addFirst(Event ev) {
104 Entry cursor = root;
105
106 if (cursor != null) {
107 while (cursor.left != null)
108 cursor = cursor.left;
109
110 Entry e = add(ev, cursor.father);
111 e.right = cursor;
112 if (cursor == root)
113 root = e;
114 else
115 cursor.father.left = e;
116 cursor.father = e;
117 } else
118 root = add(ev, null);
119
120 ++modCount;
121 }
122
123 public void addBefore(Event ev, Event other) {
124 Entry otherEntry = findEntry(other);
125 Entry evEntry = add(ev, null);
126
127 if (otherEntry == null)
128 throw new IllegalArgumentException("other not in the tree");
129
130 // insere evEntry a la place de otherEntry et otherEntry
131 // devient le fils droit de evEntry
132 if (otherEntry != root) {
133 if (otherEntry == otherEntry.father.right)
134 otherEntry.father.right = evEntry;
135 else
136 otherEntry.father.left = evEntry;
137 } else
138 root = evEntry;
139
140 evEntry.father = otherEntry.father;
141 otherEntry.father = evEntry;
142 evEntry.right = otherEntry;
143
144 // le ss-arbre de droite de otherEntry devient le
145 // ss-arbre de droite de evEntry
146 // permet que evEntry soit exactement apres
147 // otherEntry qu'importe les operations effectuees
148 evEntry.left = otherEntry.left;
149
150 if (evEntry.left != null)
151 evEntry.left.father = evEntry;
152
153 otherEntry.left = null;
154
155 ++modCount;
156 }
157
158 public void addAfter(Event ev, Event other) {
159 // on va chercher le "Entry" de other
160 Entry otherEntry = findEntry(other);
161
162 if (otherEntry == null)
163 throw new IllegalArgumentException("other not in the tree");
164
165 // otherEntry est le parent de evEntry
166 Entry evEntry = add(ev, otherEntry);
167
168 evEntry.right = otherEntry.right;
169 otherEntry.right = evEntry;
170
171 if (evEntry.right != null)
172 evEntry.right.father = evEntry;
173
174 ++modCount;
175 }
176
177 public Event getFirst() {
178 if (root == null)
179 return null;
180 Entry cursor = root;
181 while (cursor.left != null)
182 cursor = cursor.left;
183 return cursor.event;
184 }
185
186 public Event getFirstOfClass(String cl) {
187 Entry cursor = root;
188 if (root != null)
189 while (cursor.left != null)
190 cursor = cursor.left;
191
192 while (cursor != null) {
193 if (cursor.event.getClass().getName().equals(cl))
194 return cursor.event;
195 cursor = successor(cursor);
196 }
197 return null;
198 }
199
200 @SuppressWarnings("unchecked")
201 public <E extends Event> E getFirstOfClass(Class<E> cl) {
202 Entry cursor = root;
203 if (root != null)
204 while (cursor.left != null)
205 cursor = cursor.left;
206
207 while (cursor != null) {
208 if (cursor.event.getClass() == cl)
209 return (E) cursor.event;
210 cursor = successor(cursor);
211 }
212 return null;
213 }
214
215 public Iterator<Event> iterator() {
216 return listIterator();
217 }
218
219 public ListIterator<Event> listIterator() {
220 return new BTItr();
221 }
222
223 public boolean remove(Event ev) {
224 Entry evEntry = findEntry(ev);
225 if (evEntry == null)
226 return false;
227 else
228 return remove(evEntry);
229 }
230
232 if (root == null)
233 return null;
234
235 Entry cursor = root;
236 while (cursor.left != null)
237 cursor = cursor.left;
238
239 Event first = cursor.event;
240 remove(cursor);
241
242 return first;
243 }
244
245 @Override
246 public String toString() {
247 StringBuilder sb = new StringBuilder("Contents of the event list BinaryTree:");
248 Entry cursor = root;
249
250 if (root != null)
251 while (cursor.left != null)
252 cursor = cursor.left;
253
254 while (cursor != null) {
255 sb.append(PrintfFormat.NEWLINE + PrintfFormat.g(12, 7, cursor.event.time()) + ", "
256 + PrintfFormat.g(8, 4, cursor.event.priority()) + " : " + cursor.event.toString());
257 cursor = successor(cursor);
258 }
259
260 return sb.toString();
261 }
262
263 private Entry add(Event ev, Entry father) {
264 return new Entry(ev, null, null, father);
265 }
266
267 private boolean remove(Entry e) {
268 boolean filsGauche = false;
269 boolean isRoot = false;
270 Entry cursor;
271
272 if (e == root)
273 isRoot = true;
274 else {
275 if (e == e.father.left)
276 filsGauche = true;
277 else
278 filsGauche = false;
279 }
280
281 // Si condition vrai, a un fils droit ou rien
282 if (e.left == null) {
283 if (isRoot)
284 root = e.right;
285 else if (filsGauche)
286 e.father.left = e.right;
287 else
288 e.father.right = e.right;
289
290 if (e.right != null)
291 e.right.father = e.father;
292 } else if (e.right == null) {
293 // Si condition vrai, a uniquement un fils gauche
294 if (isRoot)
295 root = e.left;
296 else if (filsGauche)
297 e.father.left = e.left;
298 else
299 e.father.right = e.left;
300 e.left.father = e.father;
301 } else {
302 // a 2 fils
303 // recherche son descendant le plus petit dans le ss-arbre de droite
304 // et remplace "e" par ce descendant
305
306 cursor = e.right;
307 if (cursor.left == null) {
308 // c'est son fils de droite
309 if (isRoot)
310 root = cursor;
311 else {
312 if (filsGauche)
313 e.father.left = cursor;
314 else
315 e.father.right = cursor;
316 }
317 cursor.left = e.left;
318 } else {
319 // recherche de la plus petite valeur dans le ss-arbre droit
320 while (cursor.left != null)
321 cursor = cursor.left;
322
323 if (isRoot)
324 root = cursor;
325 else if (filsGauche)
326 e.father.left = cursor;
327 else
328 e.father.right = cursor;
329
330 // echange entre e et cursor et elimination de e
331 cursor.father.left = cursor.right;
332 if (cursor.right != null)
333 cursor.right.father = cursor.father;
334
335 cursor.right = e.right;
336 cursor.left = e.left;
337 e.right.father = cursor;
338 }
339
340 cursor.father = e.father;
341 e.left.father = cursor;
342 }
343
344 // recupere l'espace du noeud
345 e.right = null;
346 e.left = null;
347 e.event = null;
348
349 ++modCount;
350 return true;
351 }
352
353 private Entry successor(Entry cursor) {
354 if (cursor == null)
355 return null;
356
357 if (cursor.right != null) {
358 cursor = cursor.right;
359 while (cursor.left != null)
360 cursor = cursor.left;
361 } else {
362 while (cursor.father != null && cursor.father.right == cursor)
363 cursor = cursor.father;
364 cursor = cursor.father;
365 }
366 return cursor;
367 }
368
372 private Entry findEntry(Event ev) {
373 Entry cursor = root;
374 while (cursor != null) {
375 if (cursor.event == ev)
376 return cursor;
377 else if (ev.compareTo(cursor.event) < 0)
378 cursor = cursor.left;
379 else
380 cursor = cursor.right;
381 }
382 return null;
383 }
384
385 private Entry predecessor(Entry cursor) {
386 if (cursor == null)
387 return null;
388
389 if (cursor.left != null) {
390 cursor = cursor.left;
391 while (cursor.right != null)
392 cursor = cursor.right;
393 } else {
394 while (cursor.father != null && cursor.father.left == cursor)
395 cursor = cursor.father;
396 cursor = cursor.father;
397 }
398 return cursor;
399 }
400
404 private static class Entry {
405 Event event;
406 Entry right;
407 Entry left;
408 Entry father;
409
410 Entry(Event event, Entry left, Entry right, Entry father) {
411 this.event = event;
412 this.left = left;
413 this.right = right;
414 this.father = father;
415 }
416 }
417
418 private class BTItr implements ListIterator<Event> {
419 private Entry prev;
420 private Entry next;
421 private Entry lastRet;
422 private int expectedModCount;
423 private int nextIndex;
424
425 BTItr() {
426 prev = null;
427 next = root;
428 if (next != null) {
429 while (next.left != null)
430 next = next.left;
431 }
432 expectedModCount = modCount;
433 lastRet = null;
434 nextIndex = 0;
435 }
436
437 public void add(Event ev) {
438 if (modCount != expectedModCount)
439 throw new ConcurrentModificationException();
440
441 // Check the event time and priority
442 if (next != null && ev.compareTo(next.event) > 0) {
443 ev.setTime(next.event.time());
444 ev.setPriority(next.event.priority());
445 }
446 if (prev != null && ev.compareTo(prev.event) < 0) {
447 ev.setTime(prev.event.time());
448 ev.setPriority(prev.event.priority());
449 }
450
451 Entry e = BinaryTree.this.add(ev, next);
452 if (prev != null) {
453 // Ajouter ev apr`es prev.
454 // insere e comme fils droit de prev
455 e.father = prev;
456 e.right = prev.right;
457 prev.right = e;
458 if (e.right != null)
459 e.right.father = e;
460 } else {
461 // ajoute ev avant next.
462 // insere e a la place de eo et eo devient le fils droit de e
463 if (next != root) {
464 if (next == next.father.left)
465 next.father.left = e;
466 else
467 next.father.right = e;
468 } else
469 root = e;
470 e.father = prev.father;
471 prev.father = e;
472 e.left = prev;
473 // le ss-arbre de droite de eo devient le ss-arbre de droite de e
474 // permet que e soit exactement apres eo qu'importe les
475 // operations effectuees
476 e.right = prev.right;
477 if (e.right != null)
478 e.right.father = e;
479 prev.right = null;
480 }
481
482 prev = e;
483 ++nextIndex;
484 lastRet = null;
485 ++modCount;
486 ++expectedModCount;
487 }
488
489 public boolean hasNext() {
490 if (modCount != expectedModCount)
491 throw new ConcurrentModificationException();
492 return next != null;
493 }
494
495 public boolean hasPrevious() {
496 if (modCount != expectedModCount)
497 throw new ConcurrentModificationException();
498 return prev != null;
499 }
500
501 public Event next() {
502 if (!hasNext())
503 throw new NoSuchElementException();
504
505 ++nextIndex;
506 Event ev = next.event;
507 lastRet = next;
508 prev = next;
509 next = successor(next);
510 return ev;
511 }
512
513 public int nextIndex() {
514 if (!hasNext())
515 throw new NoSuchElementException();
516
517 return nextIndex;
518 }
519
520 public Event previous() {
521 if (!hasPrevious())
522 throw new NoSuchElementException();
523
524 --nextIndex;
525 Event ev = prev.event;
526 lastRet = prev;
527 next = prev;
528 prev = predecessor(prev);
529 return ev;
530 }
531
532 public int previousIndex() {
533 if (!hasPrevious())
534 throw new NoSuchElementException();
535
536 return nextIndex - 1;
537 }
538
539 public void remove() {
540 if (modCount != expectedModCount)
541 throw new ConcurrentModificationException();
542 if (lastRet == null)
543 throw new IllegalStateException();
544
545 if (lastRet == next) // Last call to previous
546 next = successor(next);
547 else { // Last call to next or no call
548 prev = predecessor(prev);
549 --nextIndex;
550 }
551 BinaryTree.this.remove(lastRet);
552 lastRet = null;
553 ++expectedModCount;
554 }
555
556 public void set(Event ev) {
557 if (modCount != expectedModCount)
558 throw new ConcurrentModificationException();
559 if (lastRet == null)
560 throw new IllegalStateException();
561
562 Entry pred = predecessor(lastRet);
563 Entry succ = successor(lastRet);
564 if (pred != null && ev.compareTo(pred.event) < 0) {
565 ev.setTime(pred.event.time());
566 ev.setPriority(pred.event.priority());
567 }
568 if (succ != null && ev.compareTo(succ.event) > 0) {
569 ev.setTime(succ.event.time());
570 ev.setPriority(succ.event.priority());
571 }
572 lastRet.event = ev;
573 }
574 }
575
576 /*
577 * public static void main (String[] args) { BinaryTree sp = new BinaryTree();
578 *
579 * Event1 e1 = new Event1(); e1.setTime(10.0); Event1 e2 = new Event1();
580 * e2.setTime(20.0); Event1 e3 = new Event1(); e3.setTime(30.0); Event1 e4 = new
581 * Event1(); e4.setTime(40.0); Event1 e5 = new Event1(); e5.setTime(50.0);
582 * Event1 e6 = new Event1(); e6.setTime(60.0); Event1 e7 = new Event1();
583 * e7.setTime(70.0);
584 *
585 * sp.add(e1); sp.add(e2); sp.print2(sp.root); sp.add(e3); sp.print2(sp.root);
586 * sp.add(e4); sp.print2(sp.root); sp.add(e5); sp.print2(sp.root); sp.add(e6);
587 * sp.print2(sp.root); sp.add(e7); sp.print2(sp.root); // sp.add(e5); //
588 * sp.print2(sp.root); sp.add(e7); sp.print2(sp.root); // sp.add(e5); //
589 * sp.print2(sp.root);
590 *
591 * sp.getFirst(); System.out.println(".....after GetFirst" +
592 * PrintfFormat.NEWLINE + PrintfFormat.NEWLINE + PrintfFormat.NEWLINE);
593 * sp.print2(sp.root); sp.remove(e3); System.out.println("Apres remove" +
594 * PrintfFormat.NEWLINE); sp.print2(sp.root); }
595 *
596 * private void print(Entry t) { if (t != null){ print (t.left);
597 * System.out.println ("===========> Event time "+t.event.time()); print
598 * (t.right); } }
599 *
600 * private void print2(Entry t) {
601 * System.out.println("=============================== "+
602 * "print2 : pour ..... "+t.event.time()); if (t != null) { System.out.println
603 * ("===========> ev time "+t.event.time()); gauche (t.left); droite
604 * (t.right); System.out.println(); } else System.out.println
605 * ("===========> gauche null "); }
606 *
607 * private void gauche (Entry t) { if (t != null) { System.out.println
608 * ("===========> gauche "+t.event.time()); gauche (t.left); droite (t.right);
609 * System.out.println(); } else System.out.println
610 * ("===========> gauche null "); }
611 *
612 * private void droite (Entry t) { if (t != null){ System.out.println
613 * ("===========> droite "+t.event.time()); gauche (t.left); droite (t.right);
614 * // System.out.println(); } else System.out.println
615 * ("===========> droite null "); }
616 *
617 * private static class Event1 extends Event { public void actions() {}
618 *
619 * public String toString() { return "Event(" + eventTime + ")"; } };
620 *
621 *
622 *
623 *
624 *
625 */
626 /*
627 * public BinaryTree() {
628 *
629 * Event1 e1 = new Event1(); e1.setTime(7.0); Event1 e2 = new Event1();
630 * e2.setTime(5.0); Event1 e3 = new Event1(); e3.setPriority(2);
631 * e3.setTime(5.0); Event1 e4 = new Event1(); e4.setTime(6.0); Event1 e5 = new
632 * Event1(); e5.setPriority(2); e5.setTime(10.0); Event1 e6 = new Event1();
633 * e6.setTime(9.0); Event1 e7 = new Event1(); e7.setTime(11.0);
634 *
635 * add(e1); add(e2); add(e3); add(e4); add(e5); add(e6); add(e7); print22(root);
636 * remove (e5); print22(root);
637 *
638 * }
639 *
640 *
641 *
642 * public void print22(Entry t) {
643 * System.out.println("racine............ ..... "+t.event.time());
644 * gauche2(t.left); droite2(t.right); System.out.println();
645 *
646 * }
647 *
648 *
649 *
650 * public void gauche2 (Entry t) { if (t!=null){ System.out.println
651 * ("===========> gauche "+t.event.time()); gauche2(t.left); droite2(t.right);
652 * System.out.println();
653 *
654 * } else System.out.println ("===========> gauche null "); }
655 *
656 * public void droite2 (Entry t) { if (t!=null){ System.out.println
657 * ("===========> droite "+t.event.time()); gauche2(t.left); droite2(t.right);
658 * // System.out.println();
659 *
660 * } else System.out.println ("===========> droite null "); }
661 */
662}
This abstract class provides event scheduling tools.
Definition Event.java:53
int compareTo(Event e)
Compares this object with the specified object e for order.
Definition Event.java:325
An implementation of EventList using a binary search tree.
void addBefore(Event ev, Event other)
Same as add, but adds the new event ev immediately before the event other in the list.
void add(Event ev)
Adds a new event in the event list, according to the time of ev.
ListIterator< Event > listIterator()
Returns a list iterator over the elements of the class Event in this list.
void addFirst(Event ev)
Adds a new event at the beginning of the event list.
Event getFirstOfClass(String cl)
Returns the first event of the class cl (a subclass of Event) in the event list.
Event getFirst()
Returns the first event in the event list.
void clear()
Empties the event list, i.e., cancels all events.
boolean isEmpty()
Returns true if and only if the event list is empty (no event is scheduled).
Event removeFirst()
Removes the first event from the event list (to cancel or execute this event).
void addAfter(Event ev, Event other)
Same as add, but adds the new event ev immediately after the event other in the list.
This class acts like a StringBuffer which defines new types of append methods.
static final String NEWLINE
End-of-line symbol or line separator.
static String g(double x)
Same as g(0, 6, x).
An interface for implementations of event lists.