Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(34)

Unified Diff: sdk/lib/collection/splay_tree.dart

Issue 12304016: Restructure SplayTreeMap to be reusable (e.g., for a SplayTreeSet). (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/corelib/map_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
}
« no previous file with comments | « no previous file | tests/corelib/map_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698