All Downloads are FREE. Search and download functionalities are using the official Maven repository.

umontreal.iro.lecuyer.simevents.eventlist.RedblackTree Maven / Gradle / Ivy

Go to download

SSJ is a Java library for stochastic simulation, developed under the direction of Pierre L'Ecuyer, in the Département d'Informatique et de Recherche Opérationnelle (DIRO), at the Université de Montréal. It provides facilities for generating uniform and nonuniform random variates, computing different measures related to probability distributions, performing goodness-of-fit tests, applying quasi-Monte Carlo methods, collecting (elementary) statistics, and programming discrete-event simulations with both events and processes.

The newest version!


/*
 * Class:        RedblackTree
 * Description:  implementation of class EventList using a red-black tree
 * Environment:  Java
 * Software:     SSJ 
 * Copyright (C) 2001  Pierre L'Ecuyer and Université de Montréal
 * Organization: DIRO, Université de Montréal
 * @author       
 * @since

 * SSJ is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License (GPL) as published by the
 * Free Software Foundation, either version 3 of the License, or
 * any later version.

 * SSJ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * A copy of the GNU General Public License is available at
   GPL licence site.
 */

package umontreal.iro.lecuyer.simevents.eventlist;

import java.util.TreeMap;
import java.util.Comparator;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.LinkedList;
import java.util.ConcurrentModificationException;
import java.util.NoSuchElementException;
import umontreal.iro.lecuyer.util.PrintfFormat;
import umontreal.iro.lecuyer.simevents.Event;
import umontreal.iro.lecuyer.simevents.Sim;


/**
 * An implementation of {@link EventList} using a red black tree,
 * which is similar to a binary search tree except that
 * every node is colored red or black.  When modifying the structure,
 * the tree is reorganized for the colors to satisfy rules that
 * give an average 
 * O(log(n)) time for removing the first event
 * or inserting a new event,
 * where n is the number of elements in the structure.
 * However, adding or removing events imply reorganizing
 * the tree and requires more overhead than a binary search tree.
 * 
 * 

* The present implementation uses the Java 2 * {@link java.util.TreeMap TreeMap} class * which implements a red black tree for general usage. * This event list implementation is not efficient. * */ public class RedblackTree implements EventList { private TreeMap tree = new TreeMap(new EventComparator()); private static Node free = null; private int modCount = 0; public void clear() { Iterator itr = tree.values().iterator(); while (itr.hasNext()) { Node node = itr.next(); node.events.clear(); itr.remove(); synchronized (RedblackTree.class) { node.nextNode = free; free = node; } } ++modCount; } public void add (Event ev) { Node node = tree.get (ev); if (node != null) node.events.add (ev); else tree.put (new EventMapKey (ev), newNode (ev)); ++modCount; } public void addFirst (Event ev) { // ev.setTime (Sim.time()); // necessaire si eventime n'est pas deja a 0 Node node = tree.get (ev); if (node != null) node.events.add (ev); else tree.put (new EventMapKey(ev), newNode (ev)); ++modCount; } public void addBefore (Event ev, Event other) { Node node = tree.get (other); if (node == null) throw new IllegalArgumentException ("Event not in list."); // ev.setTime (other.time()); node.addBefore (ev, other); ++modCount; } public void addAfter (Event ev, Event other) { Node node = tree.get (other); if (node == null) throw new IllegalArgumentException ("Event not in list."); // ev.setTime (other.time()); node.addAfter (ev, other); ++modCount; } public Event getFirst() { return isEmpty() ? null : tree.get (tree.firstKey()).events.get (0); } public Event getFirstOfClass (String cl) { Iterator itr = tree.values().iterator(); while (itr.hasNext()) { Node node = itr.next(); Event ev = node.getFirstOfClass (cl); if (ev != null) return ev; } return null; } public E getFirstOfClass (Class cl) { Iterator itr = tree.values().iterator(); while (itr.hasNext()) { Node node = itr.next(); E ev = node.getFirstOfClass (cl); if (ev != null) return ev; } return null; } public boolean remove (Event ev) { Node node = tree.get (ev); if (node == null) return false; if (node.remove (ev)) { tree.remove (ev); synchronized (RedblackTree.class) { node.nextNode = free; free = node; } } ++modCount; return true; } public Event removeFirst() { if (tree.isEmpty()) return null; Event evKey = tree.firstKey(); Node node = tree.get (evKey); Event first = node.events.get (0); node.events.remove (0); if (node.events.isEmpty()) { tree.remove (evKey); synchronized (RedblackTree.class) { node.nextNode = free; free = node; } } ++modCount; return first; } public String toString() { StringBuffer sb = new StringBuffer ("Contents of the event list RedblackTree:"); for (Node node : tree.values()) { for (Event ev : node.events) sb.append (PrintfFormat.NEWLINE + PrintfFormat.g (12, 7, ev.time()) + ", " + PrintfFormat.g (8, 4, ev.priority()) + " : " + ev.toString()); } return sb.toString(); } public Iterator iterator() { return listIterator(); } public ListIterator listIterator() { return new RBItr(); } public boolean isEmpty() { return tree.isEmpty(); } private static class Node { // For the iterator public Node prevNode = null; public Node nextNode = null; public java.util.List events = new LinkedList(); public Node (Event ev) { events.add (ev); } public void addAfter (Event ev, Event other) { ListIterator itr = events.listIterator(); while (itr.hasNext()) { Event listev = itr.next(); if (listev == other) { itr.add (ev); return; } } throw new IllegalArgumentException ("Event not in node."); } public void addBefore (Event ev, Event other) { ListIterator itr = events.listIterator(); while (itr.hasNext()) { Event listev = itr.next(); if (listev == other) { itr.previous(); itr.add (ev); return; } } throw new IllegalArgumentException ("Event not in node."); } public Event getFirstOfClass (String cl) { Iterator itr = events.iterator(); while (itr.hasNext()) { Event listev = itr.next(); if (listev.getClass().getName().equals (cl)) return listev; } return null; } @SuppressWarnings("unchecked") public E getFirstOfClass (Class cl) { Iterator itr = events.iterator(); while (itr.hasNext()) { Event listev = itr.next(); if (listev.getClass() == cl) return (E)listev; } return null; } /* * * Remove an event from a node. * Returns true if the node becomes empty. */ public boolean remove (Event ev) { Iterator itr = events.iterator(); while (itr.hasNext()) { Event listev = itr.next(); if (listev == ev) { itr.remove(); return events.isEmpty(); } } throw new IllegalArgumentException ("Event not in node."); } public String toString() { StringBuffer sb = new StringBuffer(); boolean first = true; Iterator itr = events.iterator(); while (itr.hasNext()) { if (first) first = false; else sb.append (", "); sb.append (itr.next()); } return sb.toString(); } } private static class EventComparator implements Comparator { public int compare (Event ev1, Event ev2) { return ev1.compareTo(ev2); } public boolean equals (Object obj) { return true; } } private class RBItr implements ListIterator { private int expectedModCount; private Node prevNode; private Node nextNode; private int prevNodeIndex; private int nextNodeIndex; private int nextIndex; RBItr() { expectedModCount = modCount; prevNode = null; nextNode = tree.isEmpty() ? null : (Node)tree.get (tree.firstKey()); prevNodeIndex = 0; nextNodeIndex = 0; nextIndex = 0; Iterator itr = tree.values().iterator(); Node lastNode = null; while (itr.hasNext()) { Node node = itr.next(); node.prevNode = lastNode; if (lastNode != null) lastNode.nextNode = node; node.nextNode = null; lastNode = node; } } public void add(Event ev) { throw new UnsupportedOperationException(); } public boolean hasNext() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); return nextNode != null && nextNodeIndex < nextNode.events.size(); } public boolean hasPrevious() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); return prevNode != null && prevNodeIndex >= 0; } public Event next() { if (!hasNext()) throw new NoSuchElementException(); ++nextIndex; Event ev = (Event)nextNode.events.get(nextNodeIndex); prevNode = nextNode; prevNodeIndex = nextNodeIndex; ++nextNodeIndex; if (nextNodeIndex >= nextNode.events.size()) { nextNode = nextNode.nextNode; nextNodeIndex = 0; } return ev; } public int nextIndex() { if (!hasNext()) throw new NoSuchElementException(); return nextIndex; } public Event previous() { if (!hasPrevious()) throw new NoSuchElementException(); --nextIndex; Event ev = (Event)prevNode.events.get(prevNodeIndex); nextNode = prevNode; nextNodeIndex = prevNodeIndex; --prevNodeIndex; if (prevNodeIndex < 0) { prevNode = prevNode.prevNode; if (prevNode != null) prevNodeIndex = prevNode.events.size() - 1; } return ev; } public int previousIndex() { if (!hasPrevious()) throw new NoSuchElementException(); return nextIndex - 1; } public void remove() { throw new UnsupportedOperationException(); } public void set (Event ev) { throw new UnsupportedOperationException(); } } private Node newNode (Event ev) { Node temp; synchronized (RedblackTree.class) { if (free == null) return new Node (ev); temp = free; free = free.nextNode; } temp.events.add (ev); return temp; } private class EventMapKey extends Event { public EventMapKey(Event ev) { this.eventTime = ev.time(); this.priority = ev.priority(); } public void actions() { } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy