Index: sdk/lib/collection/splay_tree.dart |
diff --git a/sdk/lib/collection/splay_tree.dart b/sdk/lib/collection/splay_tree.dart |
index 0345f8a924f73620ed7b7fa1ea3754c991bf184d..4e8362f7c38bf200a0235f92db5a1130ca811b1a 100644 |
--- a/sdk/lib/collection/splay_tree.dart |
+++ b/sdk/lib/collection/splay_tree.dart |
@@ -5,40 +5,48 @@ |
part of dart.collection; |
/** |
- * A node in a splay tree. It holds the key, the value and the left |
+ * A node in a splay tree. It holds the sorting key and the left |
* and right children in the tree. |
*/ |
-class SplayTreeNode<K, V> { |
+class _SplayTreeNode<K> { |
final K key; |
- V value; |
- SplayTreeNode<K, V> left; |
- SplayTreeNode<K, V> right; |
+ _SplayTreeNode<K> left; |
+ _SplayTreeNode<K> right; |
- SplayTreeNode(K this.key, V this.value); |
+ _SplayTreeNode(K this.key); |
} |
/** |
- * A splay tree is a self-balancing binary |
- * search tree with the additional property that recently accessed |
- * elements are quick to access again. It performs basic operations |
- * such as insertion, look-up and removal in O(log(n)) amortized time. |
+ * A node in a splay tree based map. |
* |
- * This implementation is a Dart version of the JavaScript |
- * implementation in the V8 project. |
+ * A [_SplayTreeNode] that also contains a value |
*/ |
-class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
+class _SplayTreeMapNode<K, V> extends _SplayTreeNode<K> { |
+ V value; |
+ _SplayTreeMapNode(K key, V this.value) : super(key); |
+} |
+/** |
+ * A splay tree is a self-balancing binary search tree. |
+ * |
+ * It has the additional property that recently accessed elements |
+ * are quick to access again. |
+ * It performs basic operations such as insertion, look-up and |
+ * removal, in O(log(n)) amortized time. |
+ */ |
+abstract class _SplayTree<K> { |
// The root node of the splay tree. It will contain either the last |
// element inserted, or the last element looked up. |
- SplayTreeNode<K, V> _root; |
+ _SplayTreeNode<K> _root; |
// The dummy node used when performing a splay on the tree. It is a |
// local field of the class to avoid allocating a node each time a |
// splay is performed. |
- SplayTreeNode<K, V> _dummy; |
+ // TODO(lrn); Should it be a getter backed by a static instead? |
+ _SplayTreeNode<K> _dummy = new _SplayTreeNode<K>(null); |
// Number of elements in the splay tree. |
- int _count; |
+ int _count = 0; |
/** |
* Counter incremented whenever the keys in the map changes. |
@@ -46,6 +54,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
* Used to detect concurrent modifications. |
*/ |
int _modificationCount = 0; |
+ |
/** |
* Counter incremented whenever the tree structure changes. |
* |
@@ -54,9 +63,8 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
*/ |
int _splayCount = 0; |
- SplayTreeMap() : |
- _dummy = new SplayTreeNode<K, V>(null, null), |
- _count = 0; |
+ /** Comparison used to compare keys. */ |
+ int _compare(K key1, K key2); |
/** |
* Perform the splay operation for the given key. Moves the node with |
@@ -75,9 +83,9 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
// the L tree of the algorithm. The left child of the dummy node |
// will hold the R tree of the algorithm. Using a dummy node, left |
// and right will always be nodes and we avoid special cases. |
- SplayTreeNode<K, V> left = _dummy; |
- SplayTreeNode<K, V> right = _dummy; |
- SplayTreeNode<K, V> current = _root; |
+ _SplayTreeNode<K> left = _dummy; |
+ _SplayTreeNode<K> right = _dummy; |
+ _SplayTreeNode<K> current = _root; |
int comp; |
while (true) { |
comp = current.key.compareTo(key); |
@@ -86,7 +94,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
comp = current.left.key.compareTo(key); |
if (comp > 0) { |
// Rotate right. |
- SplayTreeNode<K, V> tmp = current.left; |
+ _SplayTreeNode<K> tmp = current.left; |
current.left = tmp.right; |
tmp.right = current; |
current = tmp; |
@@ -101,7 +109,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
comp = current.right.key.compareTo(key); |
if (comp < 0) { |
// Rotate left. |
- SplayTreeNode<K, V> tmp = current.right; |
+ _SplayTreeNode<K> tmp = current.right; |
current.right = tmp.left; |
tmp.left = current; |
current = tmp; |
@@ -128,26 +136,17 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
return comp; |
} |
- V operator [](K key) { |
- if (_root != null) { |
- int comp = _splay(key); |
- if (comp == 0) return _root.value; |
- } |
- return null; |
- } |
- |
- V remove(K key) { |
+ _SplayTreeNode _remove(K key) { |
if (_root == null) return null; |
int comp = _splay(key); |
if (comp != 0) return null; |
- V value = _root.value; |
- |
+ _SplayTreeNode result = _root; |
_count--; |
// assert(_count >= 0); |
if (_root.left == null) { |
_root = _root.right; |
} else { |
- SplayTreeNode<K, V> right = _root.right; |
+ _SplayTreeNode<K> right = _root.right; |
_root = _root.left; |
// Splay to make sure that the new root has an empty right child. |
_splay(key); |
@@ -156,24 +155,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
_root.right = right; |
} |
_modificationCount++; |
- return value; |
- } |
- |
- void operator []=(K key, V value) { |
- if (_root == null) { |
- _count++; |
- _root = new SplayTreeNode(key, value); |
- _modificationCount++; |
- return; |
- } |
- // Splay on the key to move the last node on the search path for |
- // the key to the root of the tree. |
- int comp = _splay(key); |
- if (comp == 0) { |
- _root.value = value; |
- return; |
- } |
- _addNewRoot(key, value, comp); |
+ return result; |
} |
/** |
@@ -182,10 +164,14 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
* The [comp] value is the result of comparing the existing root's key |
* with key. |
*/ |
- void _addNewRoot(K key, V value, int comp) { |
- SplayTreeNode<K, V> node = new SplayTreeNode(key, value); |
- // assert(_count >= 0); |
+ void _addNewRoot(_SplayTreeNode<K> node, int comp) { |
_count++; |
+ _modificationCount++; |
+ if (_root == null) { |
+ _root = node; |
+ return; |
+ } |
+ // assert(_count >= 0); |
if (comp < 0) { |
node.left = _root; |
node.right = _root.right; |
@@ -196,20 +182,87 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
_root.left = null; |
} |
_root = node; |
+ } |
+ |
+ _SplayTreeNode get _first { |
+ if (_root == null) return null; |
+ _SplayTreeNode<K> node = _root; |
+ while (node.left != null) { |
+ node = node.left; |
+ } |
+ // Maybe implement a splay-method that can splay the minimum without |
+ // performing comparisons. |
+ _splay(node.key); |
+ return node; |
+ } |
+ |
+ _SplayTreeNode get _last { |
+ if (_root == null) return null; |
+ _SplayTreeNode<K> node = _root; |
+ while (node.right != null) { |
+ node = node.right; |
+ } |
+ // Maybe implement a splay-method that can splay the minimum without |
+ // performing comparisons. |
+ _splay(node.key); |
+ return node; |
+ } |
+ |
+ void _clear() { |
+ _root = null; |
+ _count = 0; |
_modificationCount++; |
} |
+} |
- V putIfAbsent(K key, V ifAbsent()) { |
- if (_root == null) { |
- V value = ifAbsent(); |
- if (_root != null) { |
- throw new ConcurrentModificationError(this); |
- } |
- _root = new SplayTreeNode(key, value); |
- _count++; |
- _modificationCount++; |
- return value; |
+/* |
+ * A [Map] of objects that can be ordered relative to each other. |
+ * |
+ * The map is based on a self-balancing binary tree. It allows most operations |
+ * in amortized logarithmic time. |
+ * |
+ * Keys of the map are compared using the `compare` function passed in |
+ * the constructor. If that is omitted, the objects are assumed to be |
+ * [Comparable], and are compared using their [Comparable.compareTo] |
+ * method. |
+ */ |
+class SplayTreeMap<K, V> extends _SplayTree<K> implements Map<K, V> { |
+ Comparator<K> _comparator; |
+ |
+ SplayTreeMap([int compare(K key1, K key2)]) |
+ : _comparator = (compare == null) ? Comparable.compare : compare; |
+ |
+ int _compare(K key1, K key2) => _comparator(key1, key2); |
+ |
+ SplayTreeMap._internal(); |
+ |
+ V operator [](K key) { |
+ if (_root != null) { |
+ int comp = _splay(key); |
+ if (comp == 0) return _root.value; |
+ } |
+ return null; |
+ } |
+ |
+ V remove(K key) { |
+ _SplayTreeMapNode root = _remove(key); |
+ if (root != null) return root.value; |
+ return null; |
+ } |
+ |
+ void operator []=(K key, V value) { |
+ // Splay on the key to move the last node on the search path for |
+ // the key to the root of the tree. |
+ int comp = _splay(key); |
+ if (comp == 0) { |
+ _root.value = value; |
+ return; |
} |
+ _addNewRoot(new _SplayTreeMapNode(key, value), comp); |
+ } |
+ |
+ |
+ V putIfAbsent(K key, V ifAbsent()) { |
int comp = _splay(key); |
if (comp == 0) return _root.value; |
int modificationCount = _modificationCount; |
@@ -223,7 +276,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
// Key is still not there, otherwise _modificationCount would be changed. |
assert(comp != 0); |
} |
- _addNewRoot(key, value, comp); |
+ _addNewRoot(new _SplayTreeMapNode(key, value), comp); |
return value; |
} |
@@ -234,10 +287,10 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
} |
void forEach(void f(K key, V value)) { |
- Iterator<SplayTreeNode<K, V>> nodes = |
- new _SplayTreeNodeIterator<K, V>(this); |
+ Iterator<_SplayTreeNode<K>> nodes = |
+ new _SplayTreeNodeIterator<K>(this); |
while (nodes.moveNext()) { |
- SplayTreeNode<K, V> node = nodes.current; |
+ _SplayTreeMapNode<K, V> node = nodes.current; |
f(node.key, node.value); |
} |
} |
@@ -247,8 +300,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
} |
void clear() { |
- _root = null; |
- _count = 0; |
+ _clear(); |
} |
bool containsKey(K key) { |
@@ -257,7 +309,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
bool containsValue(V value) { |
bool found = false; |
- bool visit(SplayTreeNode node) { |
+ bool visit(_SplayTreeNode node) { |
if (node == null) return false; |
if (node.value == value) return true; |
// TODO(lrn): Do we want to handle the case where node.value.operator== |
@@ -267,9 +319,9 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
return visit(_root); |
} |
- Iterable<K> get keys => new _SplayTreeKeyIterable(this); |
+ Iterable<K> get keys => new _SplayTreeKeyIterable<K>(this); |
- Iterable<V> get values => new _SplayTreeValueIterable(this); |
+ Iterable<V> get values => new _SplayTreeValueIterable<K, V>(this); |
String toString() { |
return Maps.mapToString(this); |
@@ -279,30 +331,16 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
* Get the first key in the map. Returns [null] if the map is empty. |
*/ |
K firstKey() { |
- if (_root == null) return null; |
- SplayTreeNode<K, V> node = _root; |
- while (node.left != null) { |
- node = node.left; |
- } |
- // Maybe implement a splay-method that can splay the minimum without |
- // performing comparisons. |
- _splay(node.key); |
- return node.key; |
+ _SplayTreeNode node = _first; |
+ return (node == null) ? null : node.key; |
} |
/** |
* Get the last key in the map. Returns [null] if the map is empty. |
*/ |
K lastKey() { |
- if (_root == null) return null; |
- SplayTreeNode<K, V> node = _root; |
- while (node.right != null) { |
- node = node.right; |
- } |
- // Maybe implement a splay-method that can splay the maximum without |
- // performing comparisons. |
- _splay(node.key); |
- return node.key; |
+ _SplayTreeNode node = _last; |
+ return (node == null) ? null : node.key; |
} |
/** |
@@ -313,7 +351,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
if (_root == null) return null; |
int comp = _splay(key); |
if (comp < 0) return _root.key; |
- SplayTreeNode<K, V> node = _root.left; |
+ _SplayTreeNode<K> node = _root.left; |
if (node == null) return null; |
while (node.right != null) { |
node = node.right; |
@@ -329,7 +367,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
if (_root == null) return null; |
int comp = _splay(key); |
if (comp > 0) return _root.key; |
- SplayTreeNode<K, V> node = _root.right; |
+ _SplayTreeNode<K> node = _root.right; |
if (node == null) return null; |
while (node.left != null) { |
node = node.left; |
@@ -339,7 +377,7 @@ class SplayTreeMap<K extends Comparable<K>, V> implements Map<K, V> { |
} |
abstract class _SplayTreeIterator<T> implements Iterator<T> { |
- final SplayTreeMap _map; |
+ final _SplayTree _tree; |
/** |
* Worklist of nodes to visit. |
* |
@@ -348,33 +386,33 @@ abstract class _SplayTreeIterator<T> implements Iterator<T> { |
* and their right subtrees will visit the remainder of |
* the nodes of a full traversal. |
* |
- * Only valid as long as the original tree map isn't reordered. |
+ * Only valid as long as the original tree isn't reordered. |
*/ |
- final List<SplayTreeNode> _workList = <SplayTreeNode>[]; |
+ final List<_SplayTreeNode> _workList = <_SplayTreeNode>[]; |
/** |
- * Original modification counter of [_map]. |
+ * Original modification counter of [_tree]. |
* |
- * Incremented on [_map] when a key is added or removed. |
+ * Incremented on [_tree] when a key is added or removed. |
* If it changes, iteration is aborted. |
*/ |
final int _modificationCount; |
/** |
- * Count of splay operations on [_map] when [_workList] was built. |
+ * Count of splay operations on [_tree] when [_workList] was built. |
* |
- * If the splay count on [_map] increases, [_workList] becomes invalid. |
+ * If the splay count on [_tree] increases, [_workList] becomes invalid. |
*/ |
int _splayCount; |
/** Current node. */ |
- SplayTreeNode _currentNode; |
+ _SplayTreeNode _currentNode; |
- _SplayTreeIterator(SplayTreeMap map) |
- : _map = map, |
- _modificationCount = map._modificationCount, |
- _splayCount = map._splayCount { |
- _findLeftMostDescendent(map._root); |
+ _SplayTreeIterator(_SplayTree tree) |
+ : _tree = tree, |
+ _modificationCount = tree._modificationCount, |
+ _splayCount = tree._splayCount { |
+ _findLeftMostDescendent(tree._root); |
} |
T get current { |
@@ -382,7 +420,7 @@ abstract class _SplayTreeIterator<T> implements Iterator<T> { |
return _getValue(_currentNode); |
} |
- void _findLeftMostDescendent(SplayTreeNode node) { |
+ void _findLeftMostDescendent(_SplayTreeNode node) { |
while (node != null) { |
_workList.add(node); |
node = node.left; |
@@ -390,28 +428,28 @@ abstract class _SplayTreeIterator<T> implements Iterator<T> { |
} |
/** |
- * Called when the tree structure of the map has changed. |
+ * Called when the tree structure of the tree has changed. |
* |
* This can be caused by a splay operation. |
* If the key-set changes, iteration is aborted before getting |
* here, so we know that the keys are the same as before, it's |
* only the tree that has been reordered. |
*/ |
- void _rebuildWorkList(SplayTreeNode currentNode) { |
+ void _rebuildWorkList(_SplayTreeNode currentNode) { |
assert(!_workList.isEmpty); |
_workList.clear(); |
if (currentNode == null) { |
- _findLeftMostDescendent(_map._root); |
+ _findLeftMostDescendent(_tree._root); |
} else { |
- _map._splay(currentNode.key); |
- _findLeftMostDescendent(_map._root.right); |
+ _tree._splay(currentNode.key); |
+ _findLeftMostDescendent(_tree._root.right); |
assert(!_workList.isEmpty); |
} |
} |
bool moveNext() { |
- if (_modificationCount != _map._modificationCount) { |
- throw new ConcurrentModificationError(_map); |
+ if (_modificationCount != _tree._modificationCount) { |
+ throw new ConcurrentModificationError(_tree); |
} |
// Picks the next element in the worklist as current. |
// Updates the worklist with the left-most path of the current node's |
@@ -422,7 +460,7 @@ abstract class _SplayTreeIterator<T> implements Iterator<T> { |
_currentNode = null; |
return false; |
} |
- if (_map._splayCount != _splayCount) { |
+ if (_tree._splayCount != _splayCount) { |
_rebuildWorkList(_currentNode); |
} |
_currentNode = _workList.removeLast(); |
@@ -430,34 +468,33 @@ abstract class _SplayTreeIterator<T> implements Iterator<T> { |
return true; |
} |
- T _getValue(SplayTreeNode node); |
+ T _getValue(_SplayTreeNode node); |
} |
- |
-class _SplayTreeKeyIterable<K, V> extends Iterable<K> { |
- SplayTreeMap<K, V> _map; |
- _SplayTreeKeyIterable(this._map); |
- Iterator<K> get iterator => new _SplayTreeKeyIterator<K, V>(_map); |
+class _SplayTreeKeyIterable<K> extends Iterable<K> { |
+ _SplayTree<K> _tree; |
+ _SplayTreeKeyIterable(this._tree); |
+ Iterator<K> get iterator => new _SplayTreeKeyIterator<K>(_tree); |
} |
class _SplayTreeValueIterable<K, V> extends Iterable<V> { |
SplayTreeMap<K, V> _map; |
- _SplayTreeValueIterable(this._map) ; |
+ _SplayTreeValueIterable(this._map); |
Iterator<V> get iterator => new _SplayTreeValueIterator<K, V>(_map); |
} |
-class _SplayTreeKeyIterator<K, V> extends _SplayTreeIterator<K> { |
- _SplayTreeKeyIterator(SplayTreeMap<K, V> map): super(map); |
- K _getValue(SplayTreeNode node) => node.key; |
+class _SplayTreeKeyIterator<K> extends _SplayTreeIterator<K> { |
+ _SplayTreeKeyIterator(_SplayTree<K> map): super(map); |
+ K _getValue(_SplayTreeNode node) => node.key; |
} |
class _SplayTreeValueIterator<K, V> extends _SplayTreeIterator<V> { |
_SplayTreeValueIterator(SplayTreeMap<K, V> map): super(map); |
- V _getValue(SplayTreeNode node) => node.value; |
+ V _getValue(_SplayTreeMapNode node) => node.value; |
} |
-class _SplayTreeNodeIterator<K, V> |
- extends _SplayTreeIterator<SplayTreeNode<K, V>> { |
- _SplayTreeNodeIterator(SplayTreeMap<K, V> map): super(map); |
- SplayTreeNode<K, V> _getValue(SplayTreeNode node) => node; |
+class _SplayTreeNodeIterator<K> |
+ extends _SplayTreeIterator<_SplayTreeNode<K>> { |
+ _SplayTreeNodeIterator(_SplayTree<K> map): super(map); |
+ _SplayTreeNode<K> _getValue(_SplayTreeNode node) => node; |
} |