001package components.binarytree;
002
003import java.util.Iterator;
004import java.util.NoSuchElementException;
005
006/**
007 * {@code BinaryTree} represented as a recursive data structure, done
008 * "bare-handed", with implementations of primary methods.
009 *
010 * <p>
011 * Execution-time performance of all methods implemented in this class is O(1).
012 *
013 * @param <T>
014 *            type of {@code BinaryTree} labels
015 * @mathsubtypes <pre>
016 * TREE_REP is  (
017 *   size: integer,
018 *   height: integer,
019 *   rootLabel: T,
020 *   leftSubtree: TREE_REP,
021 *   rightSubtree: TREE_REP
022 *  )
023 * </pre>
024 * @mathdefinitions {@code
025 * IS_LEGAL_REP (
026 *   tr: TREE_REP
027 *  ): boolean is
028 *  0 <= tr.height <= tr.size <= (2^tr.height - 1)  and
029 *  (if tr.size > 0 then
030 *   tr.size = 1 + tr.leftSubtree.size + tr.rightSubtree.size  and
031 *   tr.height = 1 + max(tr.leftSubtree.height, tr.rightSubtree.height)  and
032 *   [tr.rootLabel is not null]  and
033 *   [tr.leftSubtree is not null]  and
034 *   [tr.rightSubtree is not null]  and
035 *   [tr.leftSubtree and tr.rightSubtree are not aliases]  and
036 *   IS_LEGAL_REP(tr.leftSubtree)  and
037 *   IS_LEGAL_REP(tr.rightSubtree))
038 *
039 * ABSTRACT_TREE (
040 *   tr: TREE_REP
041 *  ): binary tree of T satisfies
042 *  if IS_LEGAL_REP(tr) then
043 *   (if tr.size = 0
044 *    then ABSTRACT_TREE(tr) = empty_tree
045 *    else ABSTRACT_TREE(tr) =
046 *         compose(tr.rootLabel, ABSTRACT_TREE(tr.leftSubtree),
047 *                 ABSTRACT_TREE(tr.rightSubtree)))
048 * }
049 * @convention IS_LEGAL_REP($this)
050 * @correspondence this = ABSTRACT_TREE($this)
051 */
052public class BinaryTree1<T> extends BinaryTreeSecondary<T> {
053
054    /*
055     * Private members --------------------------------------------------------
056     */
057
058    /**
059     * Size of tree.
060     */
061    private int size;
062
063    /**
064     * Height of tree.
065     */
066    private int height;
067
068    /**
069     * Root label.
070     */
071
072    private T rootLabel;
073
074    /**
075     * Left subtree.
076     */
077    private BinaryTree1<T> leftSubtree;
078
079    /**
080     * Right subtree.
081     */
082    private BinaryTree1<T> rightSubtree;
083
084    /**
085     * Creator of initial representation.
086     */
087    private void createNewRep() {
088        this.size = 0;
089        this.height = 0;
090        this.rootLabel = null;
091        this.leftSubtree = null;
092        this.rightSubtree = null;
093    }
094
095    /*
096     * Constructors -----------------------------------------------------------
097     */
098
099    /**
100     * No-argument constructor.
101     */
102    public BinaryTree1() {
103        this.createNewRep();
104    }
105
106    /*
107     * Standard methods -------------------------------------------------------
108     */
109
110    @SuppressWarnings("unchecked")
111    @Override
112    public final BinaryTree<T> newInstance() {
113        try {
114            return this.getClass().getConstructor().newInstance();
115        } catch (ReflectiveOperationException e) {
116            throw new AssertionError(
117                    "Cannot construct object of type " + this.getClass());
118        }
119    }
120
121    @Override
122    public final void clear() {
123        this.createNewRep();
124    }
125
126    @Override
127    public final void transferFrom(BinaryTree<T> source) {
128        assert source != null : "Violation of: source is not null";
129        assert source != this : "Violation of: source is not this";
130        assert source instanceof BinaryTree1<?>
131                : "Violation of: source is of dynamic type BinaryTree1<?>";
132        /*
133         * This cast cannot fail since the assert above would have stopped
134         * execution in that case: source must be of dynamic type
135         * BinaryTree1<?>, and the ? must be T or the call would not have
136         * compiled.
137         */
138        BinaryTree1<T> localSource = (BinaryTree1<T>) source;
139        this.size = localSource.size;
140        this.height = localSource.height;
141        this.rootLabel = localSource.rootLabel;
142        this.leftSubtree = localSource.leftSubtree;
143        this.rightSubtree = localSource.rightSubtree;
144        localSource.createNewRep();
145    }
146
147    /*
148     * Kernel methods ---------------------------------------------------------
149     */
150
151    @Override
152    public final void assemble(T root, BinaryTree<T> left, BinaryTree<T> right) {
153        assert root != null : "Violation of: root is not null";
154        assert left != null : "Violation of: left is not null";
155        assert right != null : "Violation of: right is not null";
156        assert left != this : "Violation of: left is not this";
157        assert right != this : "Violation of: right is not this";
158        assert left != right : "Violation of: left is not right";
159        assert left instanceof BinaryTree1<?> : "Violation of: left is a BinaryTree1<?>";
160        assert right instanceof BinaryTree1<?>
161                : "Violation of: right is a BinaryTree1<?>";
162        /*
163         * These casts cannot fail since the asserts above would have stopped
164         * execution in that case: both left and right must be of dynamic type
165         * BinaryTree1<?>, and the ? must be T or the call would not have
166         * compiled.
167         */
168        /*
169         * There's a choice here between treating parameters left and right from
170         * the client or the implementer point of view. Here we chose to use the
171         * implementer point of view because it results in (small) performance
172         * gains. Note that transferFrom is used despite this choice, which is
173         * an apparent violation of the kernel purity rule. We considered the
174         * alternative, to make a private version of transferFrom, and call it
175         * here and from the public transferFrom, and decided it was not worth
176         * doing it in this special case.
177         */
178        BinaryTree1<T> localLeft = (BinaryTree1<T>) left;
179        BinaryTree1<T> localRight = (BinaryTree1<T>) right;
180        this.size = 1 + localLeft.size + localRight.size;
181        if (localLeft.height > localRight.height) {
182            this.height = 1 + localLeft.height;
183        } else {
184            this.height = 1 + localRight.height;
185        }
186        this.rootLabel = root;
187        if (this.leftSubtree == null) {
188            this.leftSubtree = new BinaryTree1<T>();
189        }
190        this.leftSubtree.transferFrom(localLeft);
191        if (this.rightSubtree == null) {
192            this.rightSubtree = new BinaryTree1<T>();
193        }
194        this.rightSubtree.transferFrom(localRight);
195    }
196
197    @Override
198    public final T disassemble(BinaryTree<T> left, BinaryTree<T> right) {
199        assert left != null : "Violation of: left is not null";
200        assert right != null : "Violation of: right is not null";
201        assert left != this : "Violation of: left is not this";
202        assert right != this : "Violation of: right is not this";
203        assert left != right : "Violation of: left is not right";
204        assert left instanceof BinaryTree1<?> : "Violation of: left is a BinaryTree1<?>";
205        assert right instanceof BinaryTree1<?>
206                : "Violation of: right is a BinaryTree1<?>";
207        assert this.size != 0 : "Violation of: this /= empty_tree";
208        /*
209         * The casts below cannot fail since the asserts above would have
210         * stopped execution in that case: left and right must be of dynamic
211         * type BinaryTree1<?>, and the ? must be T or the call would not have
212         * compiled.
213         */
214        T localRootLabel = this.rootLabel;
215        BinaryTree1<T> localLeft = (BinaryTree1<T>) left;
216        BinaryTree1<T> localRight = (BinaryTree1<T>) right;
217        localLeft.transferFrom(this.leftSubtree);
218        localRight.transferFrom(this.rightSubtree);
219        this.createNewRep();
220        return localRootLabel;
221    }
222
223    @Override
224    public final int size() {
225        return this.size;
226    }
227
228    @Override
229    public final Iterator<T> iterator() {
230        return new BinaryTree1Iterator();
231    }
232
233    /**
234     * Regions for iterator.
235     */
236    private enum IteratorRegion {
237        /**
238         * There is no next label.
239         */
240        NONE,
241        /**
242         * Next label is from the left subtree.
243         */
244        LEFT,
245        /**
246         * Next label is from the root.
247         */
248        ROOT,
249        /**
250         * Next label is from the right subtree.
251         */
252        RIGHT
253    };
254
255    /**
256     * Implementation of {@code Iterator} interface for {@code BinaryTree1}.
257     */
258    private final class BinaryTree1Iterator implements Iterator<T> {
259
260        /**
261         * Region of tree from which next label will come.
262         */
263        private IteratorRegion region;
264
265        /**
266         * Iterator from which next label will come, if region is LEFT or RIGHT;
267         * otherwise null.
268         */
269        private Iterator<T> operative;
270
271        /**
272         * No-argument constructor.
273         */
274        private BinaryTree1Iterator() {
275            /*
276             * Iterator cannot start in right subtree, so there is no case for
277             * that.
278             */
279            if (BinaryTree1.this.size == 0) {
280                this.region = IteratorRegion.NONE;
281                this.operative = null;
282            } else if (BinaryTree1.this.leftSubtree.size > 0) {
283                this.region = IteratorRegion.LEFT;
284                this.operative = BinaryTree1.this.leftSubtree.iterator();
285            } else {
286                this.region = IteratorRegion.ROOT;
287                this.operative = null;
288            }
289        }
290
291        @Override
292        public boolean hasNext() {
293            return this.region != IteratorRegion.NONE;
294        }
295
296        @Override
297        public T next() {
298            assert this.hasNext() : "Violation of: ~this.unseen /= <>";
299            if (!this.hasNext()) {
300                /*
301                 * Exception is supposed to be thrown in this case, but with
302                 * assertion-checking enabled it cannot happen because of assert
303                 * above.
304                 */
305                throw new NoSuchElementException();
306            }
307            T result = null;
308            switch (this.region) {
309                case NONE: {
310                    /*
311                     * Cannot happen because of code above.
312                     */
313                    throw new AssertionError("Unreachable branch.");
314                }
315                case LEFT: {
316                    result = this.operative.next();
317                    if (!this.operative.hasNext()) {
318                        this.region = IteratorRegion.ROOT;
319                        this.operative = null;
320                    }
321                    break;
322                }
323                case ROOT: {
324                    result = BinaryTree1.this.rootLabel;
325                    if (BinaryTree1.this.rightSubtree.size > 0) {
326                        this.region = IteratorRegion.RIGHT;
327                        this.operative = BinaryTree1.this.rightSubtree.iterator();
328                    } else {
329                        this.region = IteratorRegion.NONE;
330                        this.operative = null;
331                    }
332                    break;
333                }
334                case RIGHT: {
335                    result = this.operative.next();
336                    if (!this.operative.hasNext()) {
337                        this.region = IteratorRegion.NONE;
338                        this.operative = null;
339                    }
340                    break;
341                }
342                default: {
343                    /*
344                     * Cannot happen because of the type of the expression.
345                     */
346                    throw new AssertionError("Unreachable branch.");
347                }
348            }
349            return result;
350        }
351
352        @Override
353        public void remove() {
354            throw new UnsupportedOperationException("remove operation not supported");
355        }
356
357    }
358
359    /*
360     * Other methods (overridden for performance reasons) ---------------------
361     */
362
363    @Override
364    public final T root() {
365        assert this.size != 0 : "Violation of: this /= empty_tree";
366        return this.rootLabel;
367    }
368
369    @Override
370    public final T replaceRoot(T x) {
371        assert this.size != 0 : "Violation of: this /= empty_tree";
372        T root = this.rootLabel;
373        this.rootLabel = x;
374        return root;
375    }
376
377    @Override
378    public final int height() {
379        return this.height;
380    }
381
382}