comparison tango/tango/util/collection/TreeBag.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*
2 File: TreeBag.d
3
4 Originally written by Doug Lea and released into the public domain.
5 Thanks for the assistance and support of Sun Microsystems Labs, Agorics
6 Inc, Loral, and everyone contributing, testing, and using this code.
7
8 History:
9 Date Who What
10 24Sep95 dl@cs.oswego.edu Create from tango.util.collection.d working file
11 13Oct95 dl Changed protection statuses
12
13 */
14
15
16 module tango.util.collection.TreeBag;
17
18 private import tango.util.collection.model.Iterator,
19 tango.util.collection.model.Comparator,
20 tango.util.collection.model.SortedValues,
21 tango.util.collection.model.GuardIterator;
22
23 private import tango.util.collection.impl.RBCell,
24 tango.util.collection.impl.BagCollection,
25 tango.util.collection.impl.AbstractIterator,
26 tango.util.collection.impl.DefaultComparator;
27
28 /**
29 * RedBlack trees.
30 * author: Doug Lea
31 **/
32
33 public class TreeBag(T) : BagCollection!(T), SortedValues!(T)
34 {
35 alias RBCell!(T) RBCellT;
36 alias Comparator!(T) ComparatorT;
37
38 alias BagCollection!(T).remove remove;
39 alias BagCollection!(T).removeAll removeAll;
40
41
42 // instance variables
43
44 /**
45 * The root of the tree. Null if empty.
46 **/
47
48 package RBCellT tree;
49
50 /**
51 * The comparator to use for ordering.
52 **/
53 protected ComparatorT cmp_;
54
55 // constructors
56
57 /**
58 * Make an empty tree.
59 * Initialize to use DefaultComparator for ordering
60 **/
61 public this ()
62 {
63 this(null, null, null, 0);
64 }
65
66 /**
67 * Make an empty tree, using the supplied element screener.
68 * Initialize to use DefaultComparator for ordering
69 **/
70
71 public this (Predicate s)
72 {
73 this(s, null, null, 0);
74 }
75
76 /**
77 * Make an empty tree, using the supplied element comparator for ordering.
78 **/
79 public this (ComparatorT c)
80 {
81 this(null, c, null, 0);
82 }
83
84 /**
85 * Make an empty tree, using the supplied element screener and comparator
86 **/
87 public this (Predicate s, ComparatorT c)
88 {
89 this(s, c, null, 0);
90 }
91
92 /**
93 * Special version of constructor needed by clone()
94 **/
95
96 protected this (Predicate s, ComparatorT cmp, RBCellT t, int n)
97 {
98 super(s);
99 count = n;
100 tree = t;
101 if (cmp !is null)
102 cmp_ = cmp;
103 else
104 cmp_ = new DefaultComparator!(T);
105 }
106
107 /**
108 * Make an independent copy of the tree. Does not clone elements.
109 **/
110
111 public TreeBag duplicate()
112 {
113 if (count is 0)
114 return new TreeBag!(T)(screener, cmp_);
115 else
116 return new TreeBag!(T)(screener, cmp_, tree.copyTree(), count);
117 }
118
119
120
121 // Collection methods
122
123 /**
124 * Implements tango.util.collection.impl.Collection.Collection.contains
125 * Time complexity: O(log n).
126 * See_Also: tango.util.collection.impl.Collection.Collection.contains
127 **/
128 public final bool contains(T element)
129 {
130 if (!isValidArg(element) || count is 0)
131 return false;
132
133 return tree.find(element, cmp_) !is null;
134 }
135
136 /**
137 * Implements tango.util.collection.impl.Collection.Collection.instances
138 * Time complexity: O(log n).
139 * See_Also: tango.util.collection.impl.Collection.Collection.instances
140 **/
141 public final uint instances(T element)
142 {
143 if (!isValidArg(element) || count is 0)
144 return 0;
145
146 return tree.count(element, cmp_);
147 }
148
149 /**
150 * Implements tango.util.collection.impl.Collection.Collection.elements
151 * Time complexity: O(1).
152 * See_Also: tango.util.collection.impl.Collection.Collection.elements
153 **/
154 public final GuardIterator!(T) elements()
155 {
156 return new CellIterator!(T)(this);
157 }
158
159 /**
160 * Implements tango.util.collection.model.View.View.opApply
161 * Time complexity: O(n).
162 * See_Also: tango.util.collection.model.View.View.opApply
163 **/
164 int opApply (int delegate (inout T value) dg)
165 {
166 auto scope iterator = new CellIterator!(T)(this);
167 return iterator.opApply (dg);
168 }
169
170
171 // ElementSortedCollection methods
172
173
174 /**
175 * Implements tango.util.collection.ElementSortedCollection.comparator
176 * Time complexity: O(1).
177 * See_Also: tango.util.collection.ElementSortedCollection.comparator
178 **/
179 public final ComparatorT comparator()
180 {
181 return cmp_;
182 }
183
184 /**
185 * Reset the comparator. Will cause a reorganization of the tree.
186 * Time complexity: O(n log n).
187 **/
188 public final void comparator(ComparatorT cmp)
189 {
190 if (cmp !is cmp_)
191 {
192 if (cmp !is null)
193 cmp_ = cmp;
194 else
195 cmp_ = new DefaultComparator!(T);
196
197 if (count !is 0)
198 { // must rebuild tree!
199 incVersion();
200 RBCellT t = tree.leftmost();
201 tree = null;
202 count = 0;
203 while (t !is null)
204 {
205 add_(t.element(), false);
206 t = t.successor();
207 }
208 }
209 }
210 }
211
212
213 // MutableCollection methods
214
215 /**
216 * Implements tango.util.collection.impl.Collection.Collection.clear.
217 * Time complexity: O(1).
218 * See_Also: tango.util.collection.impl.Collection.Collection.clear
219 **/
220 public final void clear()
221 {
222 setCount(0);
223 tree = null;
224 }
225
226 /**
227 * Implements tango.util.collection.impl.Collection.Collection.removeAll.
228 * Time complexity: O(log n * instances(element)).
229 * See_Also: tango.util.collection.impl.Collection.Collection.removeAll
230 **/
231 public final void removeAll(T element)
232 {
233 remove_(element, true);
234 }
235
236
237 /**
238 * Implements tango.util.collection.impl.Collection.Collection.removeOneOf.
239 * Time complexity: O(log n).
240 * See_Also: tango.util.collection.impl.Collection.Collection.removeOneOf
241 **/
242 public final void remove(T element)
243 {
244 remove_(element, false);
245 }
246
247 /**
248 * Implements tango.util.collection.impl.Collection.Collection.replaceOneOf
249 * Time complexity: O(log n).
250 * See_Also: tango.util.collection.impl.Collection.Collection.replaceOneOf
251 **/
252 public final void replace(T oldElement, T newElement)
253 {
254 replace_(oldElement, newElement, false);
255 }
256
257 /**
258 * Implements tango.util.collection.impl.Collection.Collection.replaceAllOf.
259 * Time complexity: O(log n * instances(oldElement)).
260 * See_Also: tango.util.collection.impl.Collection.Collection.replaceAllOf
261 **/
262 public final void replaceAll(T oldElement, T newElement)
263 {
264 replace_(oldElement, newElement, true);
265 }
266
267 /**
268 * Implements tango.util.collection.impl.Collection.Collection.take.
269 * Time complexity: O(log n).
270 * Takes the least element.
271 * See_Also: tango.util.collection.impl.Collection.Collection.take
272 **/
273 public final T take()
274 {
275 if (count !is 0)
276 {
277 RBCellT p = tree.leftmost();
278 T v = p.element();
279 tree = p.remove(tree);
280 decCount();
281 return v;
282 }
283
284 checkIndex(0);
285 return T.init; // not reached
286 }
287
288
289 // MutableBag methods
290
291 /**
292 * Implements tango.util.collection.MutableBag.addIfAbsent
293 * Time complexity: O(log n).
294 * See_Also: tango.util.collection.MutableBag.addIfAbsent
295 **/
296 public final void addIf (T element)
297 {
298 add_(element, true);
299 }
300
301
302 /**
303 * Implements tango.util.collection.MutableBag.add.
304 * Time complexity: O(log n).
305 * See_Also: tango.util.collection.MutableBag.add
306 **/
307 public final void add (T element)
308 {
309 add_(element, false);
310 }
311
312
313 // helper methods
314
315 private final void add_(T element, bool checkOccurrence)
316 {
317 checkElement(element);
318
319 if (tree is null)
320 {
321 tree = new RBCellT(element);
322 incCount();
323 }
324 else
325 {
326 RBCellT t = tree;
327
328 for (;;)
329 {
330 int diff = cmp_.compare(element, t.element());
331 if (diff is 0 && checkOccurrence)
332 return ;
333 else
334 if (diff <= 0)
335 {
336 if (t.left() !is null)
337 t = t.left();
338 else
339 {
340 tree = t.insertLeft(new RBCellT(element), tree);
341 incCount();
342 return ;
343 }
344 }
345 else
346 {
347 if (t.right() !is null)
348 t = t.right();
349 else
350 {
351 tree = t.insertRight(new RBCellT(element), tree);
352 incCount();
353 return ;
354 }
355 }
356 }
357 }
358 }
359
360
361 private final void remove_(T element, bool allOccurrences)
362 {
363 if (!isValidArg(element))
364 return ;
365
366 while (count > 0)
367 {
368 RBCellT p = tree.find(element, cmp_);
369
370 if (p !is null)
371 {
372 tree = p.remove(tree);
373 decCount();
374 if (!allOccurrences)
375 return ;
376 }
377 else
378 break;
379 }
380 }
381
382 private final void replace_(T oldElement, T newElement, bool allOccurrences)
383 {
384 if (!isValidArg(oldElement) || count is 0 || oldElement == newElement)
385 return ;
386
387 while (contains(oldElement))
388 {
389 remove(oldElement);
390 add (newElement);
391 if (!allOccurrences)
392 return ;
393 }
394 }
395
396 // ImplementationCheckable methods
397
398 /**
399 * Implements tango.util.collection.model.View.View.checkImplementation.
400 * See_Also: tango.util.collection.model.View.View.checkImplementation
401 **/
402 public override void checkImplementation()
403 {
404
405 super.checkImplementation();
406 assert(cmp_ !is null);
407 assert(((count is 0) is (tree is null)));
408 assert((tree is null || tree.size() is count));
409
410 if (tree !is null)
411 {
412 tree.checkImplementation();
413 T last = T.init;
414 RBCellT t = tree.leftmost();
415 while (t !is null)
416 {
417 T v = t.element();
418 if (last !is T.init)
419 assert(cmp_.compare(last, v) <= 0);
420 last = v;
421 t = t.successor();
422 }
423 }
424 }
425
426
427 /***********************************************************************
428
429 opApply() has migrated here to mitigate the virtual call
430 on method get()
431
432 ************************************************************************/
433
434 private static class CellIterator(T) : AbstractIterator!(T)
435 {
436 private RBCellT cell;
437
438 public this (TreeBag bag)
439 {
440 super(bag);
441
442 if (bag.tree)
443 cell = bag.tree.leftmost;
444 }
445
446 public final T get()
447 {
448 decRemaining();
449 auto v = cell.element();
450 cell = cell.successor();
451 return v;
452 }
453
454 int opApply (int delegate (inout T value) dg)
455 {
456 int result;
457
458 for (auto i=remaining(); i--;)
459 {
460 auto value = get();
461 if ((result = dg(value)) != 0)
462 break;
463 }
464 return result;
465 }
466 }
467 }
468
469
470
471 debug (Test)
472 {
473 import tango.io.Console;
474
475 void main()
476 {
477 auto bag = new TreeBag!(char[]);
478 bag.add ("bar");
479 bag.add ("barrel");
480 bag.add ("foo");
481
482 foreach (value; bag.elements) {}
483
484 auto elements = bag.elements();
485 while (elements.more)
486 auto v = elements.get();
487
488 foreach (value; bag.elements)
489 Cout (value).newline;
490
491 bag.checkImplementation();
492 }
493 }