SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
RedblackTree.java
1/*
2 * Class: RedblackTree
3 * Description: implementation of class EventList using a red-black 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.TreeMap;
28import java.util.Comparator;
29import java.util.Iterator;
30import java.util.ListIterator;
31import java.util.LinkedList;
32import java.util.ConcurrentModificationException;
33import java.util.NoSuchElementException;
34import umontreal.ssj.util.PrintfFormat;
35import umontreal.ssj.simevents.Event;
36
52public class RedblackTree implements EventList {
53 private final TreeMap<Event, Node> tree = new TreeMap<Event, Node>(new EventComparator());
54 private int modCount = 0;
55
56 public void clear() {
57 Iterator<Node> itr = tree.values().iterator();
58 while (itr.hasNext()) {
59 Node node = itr.next();
60 node.events.clear();
61 itr.remove();
62 node.nextNode = null;
63 }
64 ++modCount;
65 }
66
67 public void add(Event ev) {
68 Node node = tree.get(ev);
69 if (node != null)
70 node.events.add(ev);
71 else
72 tree.put(new EventMapKey(ev), newNode(ev));
73 ++modCount;
74 }
75
76 public void addFirst(Event ev) {
77 Node node = tree.get(ev);
78 if (node != null)
79 node.events.add(ev);
80 else
81 tree.put(new EventMapKey(ev), newNode(ev));
82 ++modCount;
83 }
84
85 public void addBefore(Event ev, Event other) {
86 Node node = tree.get(other);
87 if (node == null)
88 throw new IllegalArgumentException("Event not in list.");
89 node.addBefore(ev, other);
90 ++modCount;
91 }
92
93 public void addAfter(Event ev, Event other) {
94 Node node = tree.get(other);
95 if (node == null)
96 throw new IllegalArgumentException("Event not in list.");
97 node.addAfter(ev, other);
98 ++modCount;
99 }
100
101 public Event getFirst() {
102 return isEmpty() ? null : tree.get(tree.firstKey()).events.get(0);
103 }
104
105 public Event getFirstOfClass(String cl) {
106 Iterator<Node> itr = tree.values().iterator();
107 while (itr.hasNext()) {
108 Node node = itr.next();
109 Event ev = node.getFirstOfClass(cl);
110 if (ev != null)
111 return ev;
112 }
113 return null;
114 }
115
116 public <E extends Event> E getFirstOfClass(Class<E> cl) {
117 Iterator<Node> itr = tree.values().iterator();
118 while (itr.hasNext()) {
119 Node node = itr.next();
120 E ev = node.getFirstOfClass(cl);
121 if (ev != null)
122 return ev;
123 }
124 return null;
125 }
126
127 public boolean remove(Event ev) {
128 Node node = tree.get(ev);
129 if (node == null)
130 return false;
131 if (node.remove(ev)) {
132 tree.remove(ev);
133 node.nextNode = null;
134 }
135 ++modCount;
136 return true;
137 }
138
140 if (tree.isEmpty())
141 return null;
142 Event evKey = tree.firstKey();
143 Node node = tree.get(evKey);
144 Event first = node.events.get(0);
145 node.events.remove(0);
146 if (node.events.isEmpty()) {
147 tree.remove(evKey);
148 node.nextNode = null;
149 }
150 ++modCount;
151 return first;
152 }
153
154 public String toString() {
155 StringBuilder sb = new StringBuilder("Contents of the event list RedblackTree:");
156 for (Node node : tree.values()) {
157 for (Event ev : node.events)
158 sb.append(PrintfFormat.NEWLINE + PrintfFormat.g(12, 7, ev.time()) + ", "
159 + PrintfFormat.g(8, 4, ev.priority()) + " : " + ev.toString());
160 }
161 return sb.toString();
162 }
163
164 public Iterator<Event> iterator() {
165 return listIterator();
166 }
167
168 public ListIterator<Event> listIterator() {
169 return new RBItr();
170 }
171
172 public boolean isEmpty() {
173 return tree.isEmpty();
174 }
175
176 private static class Node {
177 // For the iterator
178 public Node prevNode = null;
179 public Node nextNode = null;
180
181 public java.util.List<Event> events = new LinkedList<Event>();
182
183 public Node(Event ev) {
184 events.add(ev);
185 }
186
187 public void addAfter(Event ev, Event other) {
188 ListIterator<Event> itr = events.listIterator();
189 while (itr.hasNext()) {
190 Event listev = itr.next();
191 if (listev == other) {
192 itr.add(ev);
193 return;
194 }
195 }
196 throw new IllegalArgumentException("Event not in node.");
197 }
198
199 public void addBefore(Event ev, Event other) {
200 ListIterator<Event> itr = events.listIterator();
201 while (itr.hasNext()) {
202 Event listev = itr.next();
203 if (listev == other) {
204 itr.previous();
205 itr.add(ev);
206 return;
207 }
208 }
209 throw new IllegalArgumentException("Event not in node.");
210 }
211
212 public Event getFirstOfClass(String cl) {
213 Iterator<Event> itr = events.iterator();
214 while (itr.hasNext()) {
215 Event listev = itr.next();
216 if (listev.getClass().getName().equals(cl))
217 return listev;
218 }
219 return null;
220 }
221
222 @SuppressWarnings("unchecked")
223 public <E extends Event> E getFirstOfClass(Class<E> cl) {
224 Iterator<Event> itr = events.iterator();
225 while (itr.hasNext()) {
226 Event listev = itr.next();
227 if (listev.getClass() == cl)
228 return (E) listev;
229 }
230 return null;
231 }
232
236 public boolean remove(Event ev) {
237 Iterator<Event> itr = events.iterator();
238 while (itr.hasNext()) {
239 Event listev = itr.next();
240 if (listev == ev) {
241 itr.remove();
242 return events.isEmpty();
243 }
244 }
245 throw new IllegalArgumentException("Event not in node.");
246 }
247
248 public String toString() {
249 StringBuilder sb = new StringBuilder();
250 boolean first = true;
251 Iterator<Event> itr = events.iterator();
252 while (itr.hasNext()) {
253 if (first)
254 first = false;
255 else
256 sb.append(", ");
257 sb.append(itr.next());
258 }
259 return sb.toString();
260 }
261 }
262
263 private static class EventComparator implements Comparator<Event> {
264
265 public int compare(Event ev1, Event ev2) {
266 return ev1.compareTo(ev2);
267 }
268 }
269
270 private class RBItr implements ListIterator<Event> {
271 private int expectedModCount;
272 private Node prevNode;
273 private Node nextNode;
274 private int prevNodeIndex;
275 private int nextNodeIndex;
276 private int nextIndex;
277
278 RBItr() {
279 expectedModCount = modCount;
280 prevNode = null;
281 nextNode = tree.isEmpty() ? null : (Node) tree.get(tree.firstKey());
282 prevNodeIndex = 0;
283 nextNodeIndex = 0;
284 nextIndex = 0;
285
286 Iterator<Node> itr = tree.values().iterator();
287 Node lastNode = null;
288 while (itr.hasNext()) {
289 Node node = itr.next();
290 node.prevNode = lastNode;
291 if (lastNode != null)
292 lastNode.nextNode = node;
293 node.nextNode = null;
294 lastNode = node;
295 }
296 }
297
298 public void add(Event ev) {
299 throw new UnsupportedOperationException();
300 }
301
302 public boolean hasNext() {
303 if (modCount != expectedModCount)
304 throw new ConcurrentModificationException();
305 return nextNode != null && nextNodeIndex < nextNode.events.size();
306 }
307
308 public boolean hasPrevious() {
309 if (modCount != expectedModCount)
310 throw new ConcurrentModificationException();
311 return prevNode != null && prevNodeIndex >= 0;
312 }
313
314 public Event next() {
315 if (!hasNext())
316 throw new NoSuchElementException();
317
318 ++nextIndex;
319 Event ev = (Event) nextNode.events.get(nextNodeIndex);
320 prevNode = nextNode;
321 prevNodeIndex = nextNodeIndex;
322 ++nextNodeIndex;
323 if (nextNodeIndex >= nextNode.events.size()) {
324 nextNode = nextNode.nextNode;
325 nextNodeIndex = 0;
326 }
327 return ev;
328 }
329
330 public int nextIndex() {
331 if (!hasNext())
332 throw new NoSuchElementException();
333
334 return nextIndex;
335 }
336
337 public Event previous() {
338 if (!hasPrevious())
339 throw new NoSuchElementException();
340
341 --nextIndex;
342 Event ev = (Event) prevNode.events.get(prevNodeIndex);
343 nextNode = prevNode;
344 nextNodeIndex = prevNodeIndex;
345 --prevNodeIndex;
346 if (prevNodeIndex < 0) {
347 prevNode = prevNode.prevNode;
348 if (prevNode != null)
349 prevNodeIndex = prevNode.events.size() - 1;
350 }
351 return ev;
352 }
353
354 public int previousIndex() {
355 if (!hasPrevious())
356 throw new NoSuchElementException();
357
358 return nextIndex - 1;
359 }
360
361 public void remove() {
362 throw new UnsupportedOperationException();
363 }
364
365 public void set(Event ev) {
366 throw new UnsupportedOperationException();
367 }
368 }
369
370 private Node newNode(Event ev) {
371 return new Node(ev);
372 }
373
374 private class EventMapKey extends Event {
375 public EventMapKey(Event ev) {
376 this.eventTime = ev.time();
377 this.priority = ev.priority();
378 }
379
380 public void actions() {
381 }
382 }
383}
This abstract class provides event scheduling tools.
Definition Event.java:53
Event()
Constructs a new event instance, which can be placed afterwards into the event list of the default si...
Definition Event.java:126
abstract void actions()
This is the method that is executed when this event occurs.
final double time()
Returns the (planned) time of occurence of this event.
Definition Event.java:279
An implementation of EventList using a red black tree, which is similar to a binary search tree excep...
void add(Event ev)
Adds a new event in the event list, according to the time of ev.
void addBefore(Event ev, Event other)
Same as add, but adds the new event ev immediately before the event other in the list.
void clear()
Empties the event list, i.e., cancels all events.
void addAfter(Event ev, Event other)
Same as add, but adds the new event ev immediately after the event other in the list.
boolean isEmpty()
Returns true if and only if the event list is empty (no event is scheduled).
Event getFirst()
Returns the first event in the event list.
ListIterator< Event > listIterator()
Returns a list iterator over the elements of the class Event in this list.
Event getFirstOfClass(String cl)
Returns the first event of the class cl (a subclass of Event) in the event list.
public< E extends Event > E getFirstOfClass(Class< E > cl)
Returns the first event of the class E (a subclass of Event) in the event list.
void addFirst(Event ev)
Adds a new event at the beginning of the event list.
Event removeFirst()
Removes the first event from the event list (to cancel or execute this event).
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.