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

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

Issue 10890030: Move core and coreimpl from corelib/ to lib/core and lib/coreimpl. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase. Created 8 years, 3 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
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * A node in a splay tree. It holds the key, the value and the left
7 * and right children in the tree.
8 */
9 class SplayTreeNode<K, V> {
10 SplayTreeNode(K this.key, V this.value);
11
12 K key;
13 V value;
14 SplayTreeNode<K, V> left;
15 SplayTreeNode<K, V> right;
16 }
17
18 /**
19 * A splay tree is a self-balancing binary
20 * search tree with the additional property that recently accessed
21 * elements are quick to access again. It performs basic operations
22 * such as insertion, look-up and removal in O(log(n)) amortized time.
23 *
24 * This implementation is a Dart version of the JavaScript
25 * implementation in the V8 project.
26 */
27 class SplayTreeMap<K extends Comparable, V> implements Map<K, V> {
28
29 // The root node of the splay tree. It will contain either the last
30 // element inserted, or the last element looked up.
31 SplayTreeNode<K, V> _root;
32
33 // The dummy node used when performing a splay on the tree. It is a
34 // local field of the class to avoid allocating a node each time a
35 // splay is performed.
36 SplayTreeNode<K, V> _dummy;
37
38 // Number of elements in the splay tree.
39 int _count;
40
41 SplayTreeMap() {
42 _dummy = new SplayTreeNode<K, V>(null, null);
43 _count = 0;
44 }
45
46 /**
47 * Perform the splay operation for the given key. Moves the node with
48 * the given key to the top of the tree. If no node has the given
49 * key, the last node on the search path is moved to the top of the
50 * tree. This is the simplified top-down splaying algorithm from:
51 * "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
52 */
53 void splay_(K key) {
54 if (isEmpty()) return;
55
56 // The right child of the dummy node will hold
57 // the L tree of the algorithm. The left child of the dummy node
58 // will hold the R tree of the algorithm. Using a dummy node, left
59 // and right will always be nodes and we avoid special cases.
60 SplayTreeNode<K, V> left = _dummy;
61 SplayTreeNode<K, V> right = _dummy;
62 SplayTreeNode<K, V> current = _root;
63 while (true) {
64 int comp = key.compareTo(current.key);
65 if (comp < 0) {
66 if (current.left === null) break;
67 if (key.compareTo(current.left.key) < 0) {
68 // Rotate right.
69 SplayTreeNode<K, V> tmp = current.left;
70 current.left = tmp.right;
71 tmp.right = current;
72 current = tmp;
73 if (current.left === null) break;
74 }
75 // Link right.
76 right.left = current;
77 right = current;
78 current = current.left;
79 } else if (comp > 0) {
80 if (current.right === null) break;
81 if (key.compareTo(current.right.key) > 0) {
82 // Rotate left.
83 SplayTreeNode<K, V> tmp = current.right;
84 current.right = tmp.left;
85 tmp.left = current;
86 current = tmp;
87 if (current.right === null) break;
88 }
89 // Link left.
90 left.right = current;
91 left = current;
92 current = current.right;
93 } else {
94 break;
95 }
96 }
97 // Assemble.
98 left.right = current.left;
99 right.left = current.right;
100 current.left = _dummy.right;
101 current.right = _dummy.left;
102 _root = current;
103
104 _dummy.right = null;
105 _dummy.left = null;
106 }
107
108 V operator [](K key) {
109 if (!isEmpty()) {
110 splay_(key);
111 if (_root.key.compareTo(key) == 0) return _root.value;
112 }
113 return null;
114 }
115
116 V remove(K key) {
117 if (isEmpty()) return null;
118 splay_(key);
119 if (_root.key.compareTo(key) != 0) return null;
120 V value = _root.value;
121
122 _count--;
123 // assert(_count >= 0);
124 if (_root.left === null) {
125 _root = _root.right;
126 } else {
127 SplayTreeNode<K, V> right = _root.right;
128 _root = _root.left;
129 // Splay to make sure that the new root has an empty right child.
130 splay_(key);
131 // Insert the original right child as the right child of the new
132 // root.
133 _root.right = right;
134 }
135 return value;
136 }
137
138 void operator []=(K key, V value) {
139 if (isEmpty()) {
140 _count++;
141 _root = new SplayTreeNode(key, value);
142 return;
143 }
144 // Splay on the key to move the last node on the search path for
145 // the key to the root of the tree.
146 splay_(key);
147 if (_root.key.compareTo(key) == 0) {
148 _root.value = value;
149 return;
150 }
151 SplayTreeNode<K, V> node = new SplayTreeNode(key, value);
152 // assert(_count >= 0);
153 _count++;
154 if (key.compareTo(_root.key) > 0) {
155 node.left = _root;
156 node.right = _root.right;
157 _root.right = null;
158 } else {
159 node.right = _root;
160 node.left = _root.left;
161 _root.left = null;
162 }
163 _root = node;
164 }
165
166 V putIfAbsent(K key, V ifAbsent()) {
167 if (containsKey(key)) return this[key];
168 V value = ifAbsent();
169 this[key] = value;
170 return value;
171 }
172
173 bool isEmpty() {
174 // assert(!((_root === null) && (_count != 0)));
175 // assert(!((_count == 0) && (_root !== null)));
176 return (_root === null);
177 }
178
179 void forEach(void f(K key, V value)) {
180 List<SplayTreeNode<K, V>> list = new List<SplayTreeNode<K, V>>();
181 SplayTreeNode<K, V> current = _root;
182 while (current !== null) {
183 if (current.left !== null) {
184 list.add(current);
185 current = current.left;
186 } else {
187 f(current.key, current.value);
188 while (current.right === null) {
189 if (list.isEmpty()) return;
190 current = list.removeLast();
191 f(current.key, current.value);
192 }
193 current = current.right;
194 }
195 }
196 }
197
198 int get length() {
199 return _count;
200 }
201
202 void clear() {
203 _root = null;
204 _count = 0;
205 }
206
207 bool containsKey(K key) {
208 if (!isEmpty()) {
209 splay_(key);
210 if (_root.key.compareTo(key) == 0) return true;
211 }
212 return false;
213 }
214
215 bool containsValue(V value) {
216 bool found = false;
217 bool visit(SplayTreeNode node) {
218 if (node === null) return false;
219 if (node.value == value) return true;
220 return visit(node.left) || visit(node.right);
221 }
222 return visit(_root);
223 }
224
225 Collection<K> getKeys() {
226 List<K> list = new List<K>();
227 forEach((K k, V v) { list.add(k); });
228 return list;
229 }
230
231 Collection<V> getValues() {
232 List<V> list = new List<V>();
233 forEach((K k, V v) { list.add(v); });
234 return list;
235 }
236
237 String toString() {
238 return Maps.mapToString(this);
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, null);
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, null);
305 }
306 }
OLDNEW
« no previous file with comments | « corelib/src/implementation/regexp.dart ('k') | corelib/src/implementation/stopwatch_implementation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698