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

Side by Side Diff: corelib/src/implementation/splay_tree.dart

Issue 9455051: Add getMinimum, getMaximum, getPreceding and getSucceeding to SplayTree. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/corelib/src/SplayTreeTest.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * A node in a splay tree. It holds the key, the value and the left 6 * A node in a splay tree. It holds the key, the value and the left
7 * and right children in the tree. 7 * and right children in the tree.
8 */ 8 */
9 class SplayTreeNode<K, V> { 9 class SplayTreeNode<K, V> {
10 SplayTreeNode(K k, V v) { 10 SplayTreeNode(K this.key, V this.value);
11 key = k;
12 value = v;
13 }
14 11
15 K key; 12 K key;
16 V value; 13 V value;
17 SplayTreeNode<K, V> left; 14 SplayTreeNode<K, V> left;
18 SplayTreeNode<K, V> right; 15 SplayTreeNode<K, V> right;
19 } 16 }
20 17
21 /** 18 /**
22 * A splay tree is a self-balancing binary 19 * A splay tree is a self-balancing binary
23 * search tree with the additional property that recently accessed 20 * search tree with the additional property that recently accessed
24 * elements are quick to access again. It performs basic operations 21 * elements are quick to access again. It performs basic operations
25 * such as insertion, look-up and removal in O(log(n)) amortized time. 22 * such as insertion, look-up and removal in O(log(n)) amortized time.
26 * 23 *
27 * This implementation is a Dart version of the JavaScript 24 * This implementation is a Dart version of the JavaScript
28 * implementation in the V8 project. 25 * implementation in the V8 project.
29 */ 26 */
30 class SplayTree<K extends Comparable, V> implements Map<K, V> { 27 class SplayTreeMap<K extends Comparable, V> implements Map<K, V> {
31 28
32 // The root node of the splay tree. It will contain either the last 29 // The root node of the splay tree. It will contain either the last
33 // element inserted, or the last element looked up. 30 // element inserted, or the last element looked up.
34 SplayTreeNode<K, V> _root; 31 SplayTreeNode<K, V> _root;
35 32
36 // The dummy node used when performing a splay on the tree. It is a 33 // The dummy node used when performing a splay on the tree. It is a
37 // local field of the class to avoid allocating a node each time a 34 // local field of the class to avoid allocating a node each time a
38 // splay is performed. 35 // splay is performed.
39 SplayTreeNode<K, V> _dummy; 36 SplayTreeNode<K, V> _dummy;
40 37
41 // Number of elements in the splay tree. 38 // Number of elements in the splay tree.
42 int _count; 39 int _count;
43 40
44 SplayTree() { 41 SplayTreeMap() {
45 _dummy = new SplayTreeNode<K, V>(null, null); 42 _dummy = new SplayTreeNode<K, V>(null, null);
46 _count = 0; 43 _count = 0;
47 } 44 }
48 45
49 /** 46 /**
50 * Perform the splay operation for the given key. Moves the node with 47 * Perform the splay operation for the given key. Moves the node with
51 * the given key to the top of the tree. If no node has the given 48 * the given key to the top of the tree. If no node has the given
52 * key, the last node on the search path is moved to the top of the 49 * key, the last node on the search path is moved to the top of the
53 * tree. This is the simplified top-down splaying algorithm from: 50 * tree. This is the simplified top-down splaying algorithm from:
54 * "Self-adjusting Binary Search Trees" by Sleator and Tarjan. 51 * "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
55 */ 52 */
56 void splay_(K key) { 53 void splay_(K key) {
57 if (isEmpty()) return; 54 if (isEmpty()) return;
58 55
59 // The right child of the dummy node will hold 56 // The right child of the dummy node will hold
60 // the L tree of the algorithm. The left child of the dummy node 57 // the L tree of the algorithm. The left child of the dummy node
61 // will hold the R tree of the algorithm. Using a dummy node, left 58 // will hold the R tree of the algorithm. Using a dummy node, left
62 // and right will always be nodes and we avoid special cases. 59 // and right will always be nodes and we avoid special cases.
63 SplayTreeNode<K, V> left = _dummy; 60 SplayTreeNode<K, V> left = _dummy;
64 SplayTreeNode<K, V> right = _dummy; 61 SplayTreeNode<K, V> right = _dummy;
65 SplayTreeNode<K, V> current = _root; 62 SplayTreeNode<K, V> current = _root;
66 while (true) { 63 while (true) {
67 if (key.compareTo(current.key) < 0) { 64 int comp = key.compareTo(current.key);
65 if (comp < 0) {
68 if (current.left === null) break; 66 if (current.left === null) break;
69 if (key.compareTo(current.left.key) < 0) { 67 if (key.compareTo(current.left.key) < 0) {
70 // Rotate right. 68 // Rotate right.
71 SplayTreeNode<K, V> tmp = current.left; 69 SplayTreeNode<K, V> tmp = current.left;
72 current.left = tmp.right; 70 current.left = tmp.right;
73 tmp.right = current; 71 tmp.right = current;
74 current = tmp; 72 current = tmp;
75 if (current.left === null) break; 73 if (current.left === null) break;
76 } 74 }
77 // Link right. 75 // Link right.
78 right.left = current; 76 right.left = current;
79 right = current; 77 right = current;
80 current = current.left; 78 current = current.left;
81 } else if (key.compareTo(current.key) > 0) { 79 } else if (comp > 0) {
82 if (current.right === null) break; 80 if (current.right === null) break;
83 if (key.compareTo(current.right.key) > 0) { 81 if (key.compareTo(current.right.key) > 0) {
84 // Rotate left. 82 // Rotate left.
85 SplayTreeNode<K, V> tmp = current.right; 83 SplayTreeNode<K, V> tmp = current.right;
86 current.right = tmp.left; 84 current.right = tmp.left;
87 tmp.left = current; 85 tmp.left = current;
88 current = tmp; 86 current = tmp;
89 if (current.right === null) break; 87 if (current.right === null) break;
90 } 88 }
91 // Link left. 89 // Link left.
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 bool containsKey(K key) { 207 bool containsKey(K key) {
210 if (!isEmpty()) { 208 if (!isEmpty()) {
211 splay_(key); 209 splay_(key);
212 if (_root.key.compareTo(key) == 0) return true; 210 if (_root.key.compareTo(key) == 0) return true;
213 } 211 }
214 return false; 212 return false;
215 } 213 }
216 214
217 bool containsValue(V value) { 215 bool containsValue(V value) {
218 bool found = false; 216 bool found = false;
219 // Note: Worst performance you can get because we don't have 217 bool visit(SplayTreeNode node) {
220 // non-local return. 218 if (node === null) return false;
221 // TODO: optimize this method with a similar code than forEach. 219 if (node.value == value) return true;
222 forEach((Object k, Object v) { if (value == v) found = true; }); 220 return visit(node.left) || visit(node.right);
223 return found; 221 }
222 return visit(_root);
224 } 223 }
225 224
226 Collection<K> getKeys() { 225 Collection<K> getKeys() {
227 List<K> list = new List<K>(); 226 List<K> list = new List<K>();
228 forEach((K k, V v) { list.add(k); }); 227 forEach((K k, V v) { list.add(k); });
229 return list; 228 return list;
230 } 229 }
231 230
232 Collection<V> getValues() { 231 Collection<V> getValues() {
233 List<V> list = new List<V>(); 232 List<V> list = new List<V>();
234 forEach((K k, V v) { list.add(v); }); 233 forEach((K k, V v) { list.add(v); });
235 return list; 234 return list;
236 } 235 }
237 236
238 String toString() { 237 String toString() {
239 return Maps.mapToString(this); 238 return Maps.mapToString(this);
240 } 239 }
240
241 /**
242 * Get the first key in the map. Returns [null] if the map is empty.
243 */
244 K firstKey() {
245 if (_root === null) return null;
246 SplayTreeNode<K, V> node = _root;
247 while (node.left !== null) {
248 node = node.left;
249 }
250 // Maybe implement a splay-method that can splay the minimum without
251 // performing comparisons.
252 splay_(node.key);
253 return node.key;
254 }
255
256 /**
257 * Get the last key in the map. Returns [null] if the map is empty.
258 */
259 K lastKey() {
260 if (_root === null) return null;
261 SplayTreeNode<K, V> node = _root;
262 while (node.right !== null) {
263 node = node.right;
264 }
265 // Maybe implement a splay-method that can splay the maximum without
266 // performing comparisons.
267 splay_(node.key);
268 return node.key;
269 }
270
271 /**
272 * Get the last key in the map that is strictly smaller than [key]. Returns
273 * [null] if no key was not found.
274 */
275 K lastKeyBefore(K key) {
276 splay_(key);
277 K visit(SplayTreeNode node, [K ifEmpty]) {
278 if (node === null) return ifEmpty;
279 if (node.key.compareTo(key) >= 0) {
280 return visit(node.left, ifEmpty);
281 }
282 if (node.key.compareTo(key) < 0) {
283 return visit(node.right, node.key);
284 }
285 }
286 return visit(_root);
287 }
288
289 /**
290 * Get the first key in the map that is strictly larger than [key]. Returns
291 * [null] if no key was not found.
292 */
293 K firstKeyAfter(K key) {
294 splay_(key);
295 K visit(SplayTreeNode node, [K ifEmpty]) {
296 if (node === null) return ifEmpty;
297 if (node.key.compareTo(key) > 0) {
298 return visit(node.left, node.key);
299 }
300 if (node.key.compareTo(key) <= 0) {
301 return visit(node.right, ifEmpty);
302 }
303 }
304 return visit(_root);
305 }
241 } 306 }
OLDNEW
« no previous file with comments | « no previous file | tests/corelib/src/SplayTreeTest.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698