00001 package ca.mcgill.sable.util;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
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 }