Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

SplayTreeMap.java

00001 package ca.mcgill.sable.util;
00002 
00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00004  * SableUtil, a clean room implementation of the Collection API.     *
00005  * Copyright (C) 1997, 1998 Etienne Gagnon (gagnon@sable.mcgill.ca). *
00006  * All rights reserved.                                              *
00007  *                                                                   *
00008  * This work was done as a project of the Sable Research Group,      *
00009  * School of Computer Science, McGill University, Canada             *
00010  * (http://www.sable.mcgill.ca/).  It is understood that any         *
00011  * modification not identified as such is not covered by the         *
00012  * preceding statement.                                              *
00013  *                                                                   *
00014  * This work is free software; you can redistribute it and/or        *
00015  * modify it under the terms of the GNU Library General Public       *
00016  * License as published by the Free Software Foundation; either      *
00017  * version 2 of the License, or (at your option) any later version.  *
00018  *                                                                   *
00019  * This work is distributed in the hope that it will be useful,      *
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of    *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *
00022  * Library General Public License for more details.                  *
00023  *                                                                   *
00024  * You should have received a copy of the GNU Library General Public *
00025  * License along with this library; if not, write to the             *
00026  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,      *
00027  * Boston, MA  02111-1307, USA.                                      *
00028  *                                                                   *
00029  * To submit a bug report, send a comment, or get the latest news on *
00030  * this project and other Sable Research Group projects, please      *
00031  * visit the web site: http://www.sable.mcgill.ca/                   *
00032  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00033 
00034 /*
00035  Reference Version
00036  -----------------
00037  This is the latest official version on which this file is based.
00038  The reference version is: $SableUtilVersion: 1.11 $
00039 
00040  Change History
00041  --------------
00042  A) Notes:
00043 
00044  Please use the following template.  Most recent changes should
00045  appear at the top of the list.
00046 
00047  - Modified on [date (March 1, 1900)] by [name]. [(*) if appropriate]
00048    [description of modification].
00049 
00050  Any Modification flagged with "(*)" was done as a project of the
00051  Sable Research Group, School of Computer Science,
00052  McGill University, Canada (http://www.sable.mcgill.ca/).
00053 
00054  You should add your copyright, using the following template, at
00055  the top of this file, along with other copyrights.
00056 
00057  *                                                                   *
00058  * Modifications by [name] are                                       *
00059  * Copyright (C) [year(s)] [your name (or company)].  All rights     *
00060  * reserved.                                                         *
00061  *                                                                   *
00062 
00063  B) Changes:
00064 
00065  - Modified on June 7, 1998 by Etienne Gagnon (gagnon@sable.mcgill.ca). (*)
00066    Changed the license.
00067 */
00068 
00069 import ca.mcgill.sable.util.Map.Entry;
00070 
00071 public class SplayTreeMap extends AbstractMap
00072 {
00073     private int size;
00074     private Comparator comparator;
00075     private Node root;
00076     private boolean toggle;
00077     private Collection entries;
00078     private transient int modCount;
00079 
00080     private class EntryCollection extends AbstractCollection
00081     {
00082         public int size()
00083         {
00084             return size;
00085         }
00086 
00087         public Iterator iterator()
00088         {
00089             return new EntryIterator();
00090         }
00091     }
00092 
00093     private class EntryIterator implements Iterator
00094     {
00095         private Node node;
00096         private Object lastKey;
00097         private int localModCount = modCount;
00098 
00099         EntryIterator()
00100         {
00101             node = root;
00102 
00103             while((node != null) && (node.getLeft() != null))
00104             {
00105                 node = node.getLeft();
00106             }
00107         }
00108 
00109         public boolean hasNext()
00110         {
00111             if(localModCount != modCount)
00112             {
00113                 throw new ConcurrentModificationException();
00114             }
00115 
00116             return node != null;
00117         }
00118 
00119         public Object next()
00120         {
00121             if(localModCount != modCount)
00122             {
00123                 throw new ConcurrentModificationException();
00124             }
00125 
00126             lastKey = node.getKey();
00127             Object result = node;
00128 
00129             if(node.getRight() != null)
00130             {
00131                 node = node.getRight();
00132 
00133                 while(node.getLeft() != null)
00134                 {
00135                     node = node.getLeft();
00136                 }
00137             }
00138             else
00139             {
00140                 Node child = node;
00141                 node = node.getParent();
00142 
00143                 while((node != null) && (child == node.getRight()))
00144                 {
00145                     child = node;
00146                     node = node.getParent();
00147                 }
00148             }
00149 
00150             return result;
00151         }
00152 
00153         public void remove()
00154         {
00155             if(localModCount != modCount)
00156             {
00157                 throw new ConcurrentModificationException();
00158             }
00159 
00160             if(lastKey == null)
00161             {
00162                 throw new java.util.NoSuchElementException();
00163             }
00164 
00165             SplayTreeMap.this.remove(lastKey);
00166             localModCount = modCount;
00167             lastKey = null;
00168         }
00169     }
00170 
00171     private static class Node extends AbstractEntry
00172     {
00173         private Object key;
00174         private Object value;
00175 
00176         private Node left;
00177         private Node right;
00178         private Node parent;
00179 
00180         Node(Object key, Object value)
00181         {
00182             if((key == null) || (value == null))
00183             {
00184                 throw new NullPointerException();
00185             }
00186 
00187             this.key = key;
00188             this.value = value;
00189         }
00190 
00191         public Object getKey()
00192         {
00193             return key;
00194         }
00195 
00196         public Object getValue()
00197         {
00198             return value;
00199         }
00200 
00201         public Object setValue(Object value)
00202         {
00203             if(value == null)
00204             {
00205                 throw new NullPointerException();
00206             }
00207 
00208             Object oldValue = this.value;
00209             this.value = value;
00210 
00211             return oldValue;
00212         }
00213 
00214         Node getLeft()
00215         {
00216             return left;
00217         }
00218 
00219         void setLeft(Node node)
00220         {
00221             if(left != null)
00222             {
00223                 left.parent = null;
00224             }
00225 
00226             if(node != null)
00227             {
00228                 if(node.parent != null)
00229                 {
00230                     node.parent.removeChild(node);
00231                 }
00232 
00233                 node.parent = this;
00234             }
00235 
00236             left = node;
00237         }
00238 
00239         Node getRight()
00240         {
00241             return right;
00242         }
00243 
00244         void setRight(Node node)
00245         {
00246             if(right != null)
00247             {
00248                 right.parent = null;
00249             }
00250 
00251             if(node != null)
00252             {
00253                 if(node.parent != null)
00254                 {
00255                     node.parent.removeChild(node);
00256                 }
00257 
00258                 node.parent = this;
00259             }
00260 
00261             right = node;
00262         }
00263 
00264         Node getParent()
00265         {
00266             return parent;
00267         }
00268 
00269         private void removeChild(Node node)
00270         {
00271             if(left == node)
00272             {
00273                 setLeft(null);
00274             }
00275 
00276             if(right == node)
00277             {
00278                 setRight(null);
00279             }
00280         }
00281     }
00282     public SplayTreeMap()
00283     {
00284     }
00285     public SplayTreeMap(Comparator comparator)
00286     {
00287         this.comparator = comparator;
00288     }
00289     public SplayTreeMap(Map map)
00290     {
00291         for(Iterator i = map.entries().iterator(); i.hasNext();)
00292         {
00293             Entry e = (Entry) i.next();
00294             put(e.getKey(), e.getValue());
00295         }
00296     }
00297     public SplayTreeMap(Map map, Comparator comparator)
00298     {
00299         this.comparator = comparator;
00300 
00301         for(Iterator i = map.entries().iterator(); i.hasNext();)
00302         {
00303             Entry e = (Entry) i.next();
00304             put(e.getKey(), e.getValue());
00305         }
00306     }
00307     public void clear()
00308     {
00309         modCount++;
00310         root = null;
00311     }
00312     public Object clone()
00313     {
00314         return new SplayTreeMap(this, comparator);
00315     }
00316     private int compare(Object key1, Object key2)
00317     {
00318         if(comparator != null)
00319         {
00320             return comparator.compare(key1, key2);
00321         }
00322 
00323         return ((Comparable) key1).compareTo(key2);
00324     }
00325     public boolean containsKey(Object key)
00326     {
00327         if(key == null)
00328         {
00329             throw new NullPointerException();
00330         }
00331 
00332         Node node = find(key);
00333 
00334         return node != null;
00335     }
00336     private Object delete(Object key)
00337     {
00338         Node node = root;
00339         Node lastVisited = null;
00340 
00341         while(node != null)
00342         {
00343             lastVisited = node;
00344 
00345             int comp = compare(key, node.getKey());
00346 
00347             if(comp == 0)
00348             {
00349                 if(node.getLeft() == null)
00350                 {
00351                     Node right = node.getRight();
00352 
00353                     if(node.getParent() == null)
00354                     {
00355                         node.setRight(null);
00356                         root = right;
00357                         return node.getValue();
00358                     }
00359 
00360                     Node parent = node.getParent();
00361 
00362                     if(node == parent.getLeft())
00363                     {
00364                         parent.setLeft(right);
00365                     }
00366                     else
00367                     {
00368                         parent.setRight(right);
00369                     }
00370 
00371                     splay(right);
00372                     return node.getValue();
00373                 }
00374 
00375                 if(node.getRight() == null)
00376                 {
00377                     Node left = node.getLeft();
00378 
00379                     if(node.getParent() == null)
00380                     {
00381                         node.setLeft(null);
00382                         root = left;
00383                         return node.getValue();
00384                     }
00385 
00386                     Node parent = node.getParent();
00387 
00388                     if(node == parent.getRight())
00389                     {
00390                         parent.setRight(left);
00391                     }
00392                     else
00393                     {
00394                         parent.setLeft(left);
00395                     }
00396 
00397                     splay(left);
00398                     return node.getValue();
00399                 }
00400 
00401                 Node leaf;
00402 
00403                 toggle = !toggle;
00404                 if(toggle)
00405                 {
00406                     leaf = node.getRight();
00407 
00408                     while(leaf.getLeft() != null)
00409                     {
00410                         leaf = leaf.getLeft();
00411                     }
00412                 }
00413                 else
00414                 {
00415                     leaf = node.getLeft();
00416 
00417                     while(leaf.getRight() != null)
00418                     {
00419                         leaf = leaf.getRight();
00420                     }
00421                 }
00422 
00423                 delete(leaf.getKey());
00424 
00425                 if(node.getParent() == null)
00426                 {
00427                     leaf.setRight(node.getRight());
00428                     leaf.setLeft(node.getLeft());
00429                     root = leaf;
00430                     return node.getValue();
00431                 }
00432 
00433                 Node parent = node.getParent();
00434 
00435                 if(node == parent.getLeft())
00436                 {
00437                     parent.setLeft(leaf);
00438                 }
00439                 else
00440                 {
00441                     parent.setRight(leaf);
00442                 }
00443 
00444                 leaf.setRight(node.getRight());
00445                 leaf.setLeft(node.getLeft());
00446 
00447                 splay(leaf);
00448                 return node.getValue();
00449             }
00450 
00451             if(comp < 0)
00452             {
00453                 node = node.getLeft();
00454             }
00455             else
00456             {
00457                 node = node.getRight();
00458             }
00459         }
00460 
00461         splay(lastVisited);
00462         return null;
00463     }
00464     public Collection entries()
00465     {
00466         if(entries == null)
00467         {
00468             entries = new EntryCollection();
00469         }
00470 
00471         return entries;
00472     }
00473     private Node find(Object key)
00474     {
00475         Node node = root;
00476         Node lastVisited = null;
00477 
00478         while(node != null)
00479         {
00480             lastVisited = node;
00481 
00482             int comp = compare(key, node.getKey());
00483 
00484             if(comp == 0)
00485             {
00486                 splay(node);
00487                 return node;
00488             }
00489 
00490             if(comp < 0)
00491             {
00492                 node = node.getLeft();
00493             }
00494             else
00495             {
00496                 node = node.getRight();
00497             }
00498         }
00499 
00500         splay(lastVisited);
00501         return null;
00502     }
00503     public Object get(Object key)
00504     {
00505         if(key == null)
00506         {
00507             throw new NullPointerException();
00508         }
00509 
00510         Node node = find(key);
00511 
00512         if(node != null)
00513         {
00514             return node.getValue();
00515         }
00516 
00517         return null;
00518     }
00519     public Comparator getComparator()
00520     {
00521         return comparator;
00522     }
00523     private Object insert(Object key, Object value)
00524     {
00525         Node node = root;
00526         Node lastVisited = null;
00527 
00528         while(node != null)
00529         {
00530             lastVisited = node;
00531 
00532             int comp = compare(key, node.getKey());
00533 
00534             if(comp == 0)
00535             {
00536                 Object oldValue = node.getValue();
00537                 node.setValue(value);
00538                 splay(node);
00539                 return oldValue;
00540             }
00541 
00542             if(comp < 0)
00543             {
00544                 node = node.getLeft();
00545             }
00546             else
00547             {
00548                 node = node.getRight();
00549             }
00550         }
00551 
00552         if(lastVisited != null)
00553         {
00554             int comp = compare(key, lastVisited.getKey());
00555 
00556             if(comp < 0)
00557             {
00558                 lastVisited.setLeft(new Node(key, value));
00559                 splay(lastVisited.getLeft());
00560                 return null;
00561             }
00562             else
00563             {
00564                 lastVisited.setRight(new Node(key, value));
00565                 splay(lastVisited.getRight());
00566                 return null;
00567             }
00568         }
00569 
00570         compare(key, key);
00571         root = new Node(key, value);
00572         return null;
00573     }
00574     public Object put(Object key, Object value)
00575     {
00576         modCount++;
00577         Object result = insert(key, value);
00578 
00579         if(result == null)
00580         {
00581             size++;
00582         }
00583 
00584         return result;
00585     }
00586     public Object remove(Object key)
00587     {
00588         modCount++;
00589         Object result = delete(key);
00590 
00591         if(result != null)
00592         {
00593             size--;
00594         }
00595 
00596         return result;
00597     }
00598     public int size()
00599     {
00600         return size;
00601     }
00602     private void splay(Node node)
00603     {
00604         if(node == null)
00605         {
00606             return;
00607         }
00608 
00609         while(node.getParent() != null)
00610         {
00611             Node parent = node.getParent();
00612             Node grandParent = parent.getParent();
00613 
00614             if(grandParent == null)
00615             {
00616                 if(node == parent.getLeft())
00617                 {
00618                     parent.setLeft(node.getRight());
00619                     node.setRight(parent);
00620                 }
00621                 else
00622                 {
00623                     parent.setRight(node.getLeft());
00624                     node.setLeft(parent);
00625                 }
00626             }
00627             else
00628             {
00629                 Node grandGrandParent = grandParent.getParent();
00630                 boolean grandParentIsLeft = false;
00631 
00632                 if(grandGrandParent != null)
00633                 {
00634                     if(grandParent == grandGrandParent.getLeft())
00635                     {
00636                         grandParentIsLeft = true;
00637                     }
00638                 }
00639 
00640                 if(parent == grandParent.getLeft())
00641                 {
00642                     if(node == parent.getLeft())
00643                     {
00644                         grandParent.setLeft(parent.getRight());
00645                         parent.setRight(grandParent);
00646                         parent.setLeft(node.getRight());
00647                         node.setRight(parent);
00648                     }
00649                     else
00650                     {
00651                         grandParent.setLeft(node.getRight());
00652                         node.setRight(grandParent);
00653                         parent.setRight(node.getLeft());
00654                         node.setLeft(parent);
00655                     }
00656                 }
00657                 else
00658                 {
00659                     if(node == parent.getRight())
00660                     {
00661                         grandParent.setRight(parent.getLeft());
00662                         parent.setLeft(grandParent);
00663                         parent.setRight(node.getLeft());
00664                         node.setLeft(parent);
00665                     }
00666                     else
00667                     {
00668                         grandParent.setRight(node.getLeft());
00669                         node.setLeft(grandParent);
00670                         parent.setLeft(node.getRight());
00671                         node.setRight(parent);
00672                     }
00673                 }
00674 
00675                 if(grandGrandParent != null)
00676                 {
00677                     if(grandParentIsLeft)
00678                     {
00679                         grandGrandParent.setLeft(node);
00680                     }
00681                     else
00682                     {
00683                         grandGrandParent.setRight(node);
00684                     }
00685                 }
00686             }
00687         }
00688 
00689         root = node;
00690     }
00691 }

Generated at Thu Feb 7 06:55:33 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001