diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tango/tango/util/collection/TreeBag.d	Fri Jan 11 17:57:40 2008 +0100
@@ -0,0 +1,493 @@
+/*
+ File: TreeBag.d
+
+ Originally written by Doug Lea and released into the public domain. 
+ Thanks for the assistance and support of Sun Microsystems Labs, Agorics 
+ Inc, Loral, and everyone contributing, testing, and using this code.
+
+ History:
+ Date     Who                What
+ 24Sep95  dl@cs.oswego.edu   Create from tango.util.collection.d  working file
+ 13Oct95  dl                 Changed protection statuses
+
+*/
+
+
+module tango.util.collection.TreeBag;
+
+private import  tango.util.collection.model.Iterator,
+                tango.util.collection.model.Comparator,
+                tango.util.collection.model.SortedValues,
+                tango.util.collection.model.GuardIterator;
+
+private import  tango.util.collection.impl.RBCell,
+                tango.util.collection.impl.BagCollection,
+                tango.util.collection.impl.AbstractIterator,
+                tango.util.collection.impl.DefaultComparator;
+
+/**
+ * RedBlack trees.
+ * author: Doug Lea
+**/
+
+public class TreeBag(T) : BagCollection!(T), SortedValues!(T)
+{
+        alias RBCell!(T)        RBCellT;
+        alias Comparator!(T)    ComparatorT;
+
+        alias BagCollection!(T).remove     remove;
+        alias BagCollection!(T).removeAll  removeAll;
+
+
+        // instance variables
+
+        /**
+         * The root of the tree. Null if empty.
+        **/
+
+        package RBCellT tree;
+
+        /**
+         * The comparator to use for ordering.
+        **/
+        protected ComparatorT cmp_;
+
+        // constructors
+
+        /**
+         * Make an empty tree.
+         * Initialize to use DefaultComparator for ordering
+        **/
+        public this ()
+        {
+                this(null, null, null, 0);
+        }
+
+        /**
+         * Make an empty tree, using the supplied element screener.
+         * Initialize to use DefaultComparator for ordering
+        **/
+
+        public this (Predicate s)
+        {
+                this(s, null, null, 0);
+        }
+
+        /**
+         * Make an empty tree, using the supplied element comparator for ordering.
+        **/
+        public this (ComparatorT c)
+        {
+                this(null, c, null, 0);
+        }
+
+        /**
+         * Make an empty tree, using the supplied element screener and comparator
+        **/
+        public this (Predicate s, ComparatorT c)
+        {
+                this(s, c, null, 0);
+        }
+
+        /**
+         * Special version of constructor needed by clone()
+        **/
+
+        protected this (Predicate s, ComparatorT cmp, RBCellT t, int n)
+        {
+                super(s);
+                count = n;
+                tree = t;
+                if (cmp !is null)
+                    cmp_ = cmp;
+                else
+                   cmp_ = new DefaultComparator!(T);
+        }
+
+        /**
+         * Make an independent copy of the tree. Does not clone elements.
+        **/ 
+
+        public TreeBag duplicate()
+        {
+                if (count is 0)
+                    return new TreeBag!(T)(screener, cmp_);
+                else
+                   return new TreeBag!(T)(screener, cmp_, tree.copyTree(), count);
+        }
+
+
+
+        // Collection methods
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.contains
+         * Time complexity: O(log n).
+         * See_Also: tango.util.collection.impl.Collection.Collection.contains
+        **/
+        public final bool contains(T element)
+        {
+                if (!isValidArg(element) || count is 0)
+                     return false;
+
+                return tree.find(element, cmp_) !is null;
+        }
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.instances
+         * Time complexity: O(log n).
+         * See_Also: tango.util.collection.impl.Collection.Collection.instances
+        **/
+        public final uint instances(T element)
+        {
+                if (!isValidArg(element) || count is 0)
+                     return 0;
+
+                return tree.count(element, cmp_);
+        }
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.elements
+         * Time complexity: O(1).
+         * See_Also: tango.util.collection.impl.Collection.Collection.elements
+        **/
+        public final GuardIterator!(T) elements()
+        {
+                return new CellIterator!(T)(this);
+        }
+
+        /**
+         * Implements tango.util.collection.model.View.View.opApply
+         * Time complexity: O(n).
+         * See_Also: tango.util.collection.model.View.View.opApply
+        **/
+        int opApply (int delegate (inout T value) dg)
+        {
+                auto scope iterator = new CellIterator!(T)(this);
+                return iterator.opApply (dg);
+        }
+
+
+        // ElementSortedCollection methods
+
+
+        /**
+         * Implements tango.util.collection.ElementSortedCollection.comparator
+         * Time complexity: O(1).
+         * See_Also: tango.util.collection.ElementSortedCollection.comparator
+        **/
+        public final ComparatorT comparator()
+        {
+                return cmp_;
+        }
+
+        /**
+         * Reset the comparator. Will cause a reorganization of the tree.
+         * Time complexity: O(n log n).
+        **/
+        public final void comparator(ComparatorT cmp)
+        {
+                if (cmp !is cmp_)
+                   {
+                   if (cmp !is null)
+                       cmp_ = cmp;
+                   else
+                      cmp_ = new DefaultComparator!(T);
+
+                   if (count !is 0)
+                      {       // must rebuild tree!
+                      incVersion();
+                      RBCellT t = tree.leftmost();
+                      tree = null;
+                      count = 0;
+                      while (t !is null)
+                            {
+                            add_(t.element(), false);
+                            t = t.successor();
+                            }
+                      }
+                   }
+        }
+
+
+        // MutableCollection methods
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.clear.
+         * Time complexity: O(1).
+         * See_Also: tango.util.collection.impl.Collection.Collection.clear
+        **/
+        public final void clear()
+        {
+                setCount(0);
+                tree = null;
+        }
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.removeAll.
+         * Time complexity: O(log n * instances(element)).
+         * See_Also: tango.util.collection.impl.Collection.Collection.removeAll
+        **/
+        public final void removeAll(T element)
+        {
+                remove_(element, true);
+        }
+
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.removeOneOf.
+         * Time complexity: O(log n).
+         * See_Also: tango.util.collection.impl.Collection.Collection.removeOneOf
+        **/
+        public final void remove(T element)
+        {
+                remove_(element, false);
+        }
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.replaceOneOf
+         * Time complexity: O(log n).
+         * See_Also: tango.util.collection.impl.Collection.Collection.replaceOneOf
+        **/
+        public final void replace(T oldElement, T newElement)
+        {
+                replace_(oldElement, newElement, false);
+        }
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.replaceAllOf.
+         * Time complexity: O(log n * instances(oldElement)).
+         * See_Also: tango.util.collection.impl.Collection.Collection.replaceAllOf
+        **/
+        public final void replaceAll(T oldElement, T newElement)
+        {
+                replace_(oldElement, newElement, true);
+        }
+
+        /**
+         * Implements tango.util.collection.impl.Collection.Collection.take.
+         * Time complexity: O(log n).
+         * Takes the least element.
+         * See_Also: tango.util.collection.impl.Collection.Collection.take
+        **/
+        public final T take()
+        {
+                if (count !is 0)
+                   {
+                   RBCellT p = tree.leftmost();
+                   T v = p.element();
+                   tree = p.remove(tree);
+                   decCount();
+                   return v;
+                   }
+
+                checkIndex(0);
+                return T.init; // not reached
+        }
+
+
+        // MutableBag methods
+
+        /**
+         * Implements tango.util.collection.MutableBag.addIfAbsent
+         * Time complexity: O(log n).
+         * See_Also: tango.util.collection.MutableBag.addIfAbsent
+        **/
+        public final void addIf (T element)
+        {
+                add_(element, true);
+        }
+
+
+        /**
+         * Implements tango.util.collection.MutableBag.add.
+         * Time complexity: O(log n).
+         * See_Also: tango.util.collection.MutableBag.add
+        **/
+        public final void add (T element)
+        {
+                add_(element, false);
+        }
+
+
+        // helper methods
+
+        private final void add_(T element, bool checkOccurrence)
+        {
+                checkElement(element);
+
+                if (tree is null)
+                   {
+                   tree = new RBCellT(element);
+                   incCount();
+                   }
+                else
+                   {
+                   RBCellT t = tree;
+
+                   for (;;)
+                       {
+                       int diff = cmp_.compare(element, t.element());
+                       if (diff is 0 && checkOccurrence)
+                           return ;
+                       else
+                          if (diff <= 0)
+                             {
+                             if (t.left() !is null)
+                                 t = t.left();
+                             else
+                                {
+                                tree = t.insertLeft(new RBCellT(element), tree);
+                                incCount();
+                                return ;
+                                }
+                             }
+                          else
+                             {
+                             if (t.right() !is null)
+                                 t = t.right();
+                              else
+                                 {
+                                 tree = t.insertRight(new RBCellT(element), tree);
+                                 incCount();
+                                 return ;
+                                 }
+                              }
+                          }
+                   }
+        }
+
+
+        private final void remove_(T element, bool allOccurrences)
+        {
+                if (!isValidArg(element))
+                    return ;
+
+                while (count > 0)
+                      {
+                      RBCellT p = tree.find(element, cmp_);
+
+                      if (p !is null)
+                         {
+                         tree = p.remove(tree);
+                         decCount();
+                         if (!allOccurrences)
+                             return ;
+                         }
+                      else
+                         break;
+                      }
+        }
+
+        private final void replace_(T oldElement, T newElement, bool allOccurrences)
+        {
+                if (!isValidArg(oldElement) || count is 0 || oldElement == newElement)
+                    return ;
+
+                while (contains(oldElement))
+                      {
+                      remove(oldElement);
+                      add (newElement);
+                      if (!allOccurrences)
+                          return ;
+                      }
+        }
+
+        // ImplementationCheckable methods
+
+        /**
+         * Implements tango.util.collection.model.View.View.checkImplementation.
+         * See_Also: tango.util.collection.model.View.View.checkImplementation
+        **/
+        public override void checkImplementation()
+        {
+
+                super.checkImplementation();
+                assert(cmp_ !is null);
+                assert(((count is 0) is (tree is null)));
+                assert((tree is null || tree.size() is count));
+
+                if (tree !is null)
+                   {
+                   tree.checkImplementation();
+                   T last = T.init;
+                   RBCellT t = tree.leftmost();
+                   while (t !is null)
+                         {
+                         T v = t.element();
+                         if (last !is T.init)
+                             assert(cmp_.compare(last, v) <= 0);
+                         last = v;
+                         t = t.successor();
+                         }
+                   }
+        }
+
+
+        /***********************************************************************
+
+                opApply() has migrated here to mitigate the virtual call
+                on method get()
+                
+        ************************************************************************/
+
+        private static class CellIterator(T) : AbstractIterator!(T)
+        {
+                private RBCellT cell;
+
+                public this (TreeBag bag)
+                {
+                        super(bag);
+
+                        if (bag.tree)
+                            cell = bag.tree.leftmost;
+                }
+
+                public final T get()
+                {
+                        decRemaining();
+                        auto v = cell.element();
+                        cell = cell.successor();
+                        return v;
+                }
+
+                int opApply (int delegate (inout T value) dg)
+                {
+                        int result;
+
+                        for (auto i=remaining(); i--;)
+                            {
+                            auto value = get();
+                            if ((result = dg(value)) != 0)
+                                 break;
+                            }
+                        return result;
+                }
+        }
+}
+
+
+
+debug (Test)
+{
+        import tango.io.Console;
+        
+        void main()
+        {
+                auto bag = new TreeBag!(char[]);
+                bag.add ("bar");
+                bag.add ("barrel");
+                bag.add ("foo");
+
+                foreach (value; bag.elements) {}
+
+                auto elements = bag.elements();
+                while (elements.more)
+                       auto v = elements.get();
+
+                foreach (value; bag.elements)
+                         Cout (value).newline;
+                     
+                bag.checkImplementation();
+        }
+}