001/*
002 * Java Genetic Algorithm Library (jenetics-7.0.0).
003 * Copyright (c) 2007-2022 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020package io.jenetics.ext.util;
021
022import static java.lang.String.format;
023import static java.util.Objects.requireNonNull;
024import static java.util.Spliterators.spliteratorUnknownSize;
025import static io.jenetics.internal.util.SerialIO.readIntArray;
026import static io.jenetics.internal.util.SerialIO.writeIntArray;
027
028import java.io.DataInput;
029import java.io.DataOutput;
030import java.io.IOException;
031import java.io.InvalidObjectException;
032import java.io.ObjectInputStream;
033import java.io.Serial;
034import java.io.Serializable;
035import java.util.Arrays;
036import java.util.Iterator;
037import java.util.Objects;
038import java.util.Optional;
039import java.util.Spliterator;
040import java.util.Spliterators;
041import java.util.function.Function;
042import java.util.stream.Stream;
043import java.util.stream.StreamSupport;
044
045import io.jenetics.util.ISeq;
046import io.jenetics.util.Self;
047
048/**
049 * General purpose tree structure. The interface only contains tree read methods.
050 * For a mutable tree implementation have a look at the {@link TreeNode} class.
051 *
052 * @see TreeNode
053 *
054 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
055 * @version 7.0
056 * @since 3.9
057 */
058public interface Tree<V, T extends Tree<V, T>> extends Self<T>, Iterable<T> {
059
060        /* *************************************************************************
061         * Basic (abstract) operations. All other tree operations can be derived
062         * from these methods.
063         **************************************************************************/
064
065        /**
066         * Return the value of the current {@code Tree} node. The value may be
067         * {@code null}.
068         *
069         * @return the value of the current {@code Tree} node
070         */
071        V value();
072
073        /**
074         * Return the <em>parent</em> node of this tree node.
075         *
076         * @return the parent node, or {@code Optional.empty()} if this node is the
077         *         root of the tree
078         */
079        Optional<T> parent();
080
081        /**
082         * Return the child node with the given index.
083         *
084         * @param index the child index
085         * @return the child node with the given index
086         * @throws IndexOutOfBoundsException  if the {@code index} is out of
087         *         bounds ({@code [0, childCount())})
088         */
089        T childAt(final int index);
090
091        /**
092         * Return the number of children this tree node consists of.
093         *
094         * @return the number of children this tree node consists of
095         */
096        int childCount();
097
098
099        /* *************************************************************************
100         * Derived operations
101         **************************************************************************/
102
103        /**
104         * Return an iterator of the children of this {@code Tree} node.
105         *
106         * @return an iterator of the children of this {@code Tree} node.
107         */
108        default Iterator<T> childIterator() {
109                return new TreeChildIterator<V, T>(self());
110        }
111
112        /**
113         * Return a forward-order stream of this node's children.
114         *
115         * @return a stream of children of {@code this} node
116         */
117        default Stream<T> childStream() {
118                return StreamSupport.stream(
119                        Spliterators.spliterator(
120                                childIterator(),
121                                childCount(),
122                                Spliterator.SIZED | Spliterator.ORDERED
123                        ),
124                        false
125                );
126        }
127
128        /**
129         * Returns {@code true} if this node is the root of the tree.
130         *
131         * @return {@code true} if this node is the root of its tree, {@code false}
132         *         otherwise
133         */
134        default boolean isRoot() {
135                return parent().isEmpty();
136        }
137
138        /**
139         * Returns the depth of the tree rooted at this node. The <i>depth</i> of a
140         * tree is the longest distance from {@code this} node to a leaf. If
141         * {@code this} node has no children, 0 is returned. This operation is much
142         * more expensive than {@link #level()} because it must effectively traverse
143         * the entire tree rooted at {@code this} node.
144         *
145         * @return the depth of the tree whose root is this node
146         */
147        default int depth() {
148                final Iterator<T> it = breadthFirstIterator();
149
150                T last = null;
151                while (it.hasNext()) {
152                        last = it.next();
153                }
154
155                assert last != null;
156                return last.level() - level();
157        }
158
159        /**
160         * Returns the number of levels above this node. The <i>level</i> of a tree
161         * is the distance from the root to {@code this} node. If {@code this} node
162         * is the root, returns 0.
163         *
164         * @return the number of levels above this node
165         */
166        default int level() {
167                Optional<T> ancestor = Optional.of(self());
168                int levels = 0;
169                while ((ancestor = ancestor.flatMap(Tree::parent)).isPresent()) {
170                        ++levels;
171                }
172
173                return levels;
174        }
175
176        /**
177         * Returns the index of the specified child in this node's child array, or
178         * {@code -1} if {@code this} node doesn't contain the given {@code child}.
179         * This method performs a linear search and is O(n) where {@code n} is the
180         * number of children.
181         *
182         * @param child  the TreeNode to search for among this node's children
183         * @throws NullPointerException if the given {@code child} is {@code null}
184         * @return the index of the node in this node's child array, or {@code -1}
185         *         if the node could not be found
186         */
187        default int indexOf(final Tree<?, ?> child) {
188                int index = -1;
189                for (int i = 0, n = childCount(); i < n && index == -1; ++i) {
190                        if (childAt(i).identical(child)) {
191                                index = i;
192                        }
193                }
194
195                return index;
196        }
197
198        /**
199         * Return the number of nodes of {@code this} node (sub-tree).
200         *
201         * @return the number of nodes of {@code this} node (sub-tree)
202         */
203        default int size() {
204                return Trees.countChildren(this) + 1;
205        }
206
207        /**
208         * A tree is considered <em>empty</em> if it's {@link #value()} is
209         * {@code null} and has no children and parent. A newly created tree node
210         * with no value is <em>empty</em>.
211         *
212         * <pre>{@code
213         * final Tree<String, ?> tree = TreeNode.of();
214         * assert tree.isEmpty();
215         * }</pre>
216         *
217         * @since 7.0
218         *
219         * @return {@code true} if {@code this} tree is empty, {@code false}
220         *          otherwise
221         */
222        default boolean isEmpty() {
223                return value() == null && childCount() == 0 && parent().isEmpty();
224        }
225
226
227        /* *************************************************************************
228         * Query operations
229         **************************************************************************/
230
231        /**
232         * Return the child node at the given {@code path}. A path consists of the
233         * child index at a give level, starting with level 1. (The root note has
234         * level zero.) {@code tree.childAtPath(Path.of(2))} will return the third
235         * child node of {@code this} node, if it exists and
236         * {@code tree.childAtPath(Path.of(2, 0))} will return the first child of
237         * the third child of {@code this node}.
238         *
239         * @since 4.4
240         *
241         * @see #childAtPath(int...)
242         *
243         * @param path the child path
244         * @return the child node at the given {@code path}
245         * @throws NullPointerException if the given {@code path} array is
246         *         {@code null}
247         */
248        default Optional<T> childAtPath(final Path path) {
249                T node = self();
250                for (int i = 0; i < path.length() && node != null; ++i) {
251                        node = path.get(i) < node.childCount()
252                                ? node.childAt(path.get(i))
253                                : null;
254                }
255
256                return Optional.ofNullable(node);
257        }
258
259        /**
260         * Return the child node at the given {@code path}. A path consists of the
261         * child index at a give level, starting with level 1. (The root note has
262         * level zero.) {@code tree.childAtPath(2)} will return the third child node
263         * of {@code this} node, if it exists and {@code tree.childAtPath(2, 0)} will
264         * return the first child of the third child of {@code this node}.
265         *
266         * @since 4.3
267         *
268         * @see #childAtPath(Path)
269         *
270         * @param path the child path
271         * @return the child node at the given {@code path}
272         * @throws NullPointerException if the given {@code path} array is
273         *         {@code null}
274         * @throws IllegalArgumentException if one of the path elements is smaller
275         *         than zero
276         */
277        default Optional<T> childAtPath(final int... path) {
278                return childAtPath(Path.of(path));
279        }
280
281        /**
282         * Return {@code true} if the given {@code node} is an ancestor of
283         * {@code this} node. This operation is at worst {@code O(h)} where {@code h}
284         * is the distance from the root to {@code this} node.
285         *
286         * @param node the node to test
287         * @return {@code true} if the given {@code node} is an ancestor of
288         *         {@code this} node, {@code false} otherwise
289         * @throws NullPointerException if the given {@code node} is {@code null}
290         */
291        default boolean isAncestor(final Tree<?, ?> node) {
292                requireNonNull(node);
293
294                Optional<T> ancestor = Optional.of(self());
295                boolean result;
296                do {
297                        result = ancestor.filter(a -> a.identical(node)).isPresent();
298                } while (!result &&
299                                (ancestor = ancestor.flatMap(Tree::parent)).isPresent());
300
301                return result;
302        }
303
304        /**
305         * Return {@code true} if the given {@code node} is a descendant of
306         * {@code this} node. If the given {@code node} is {@code null},
307         * {@code false} is returned. This operation is at worst {@code O(h)} where
308         * {@code h} is the distance from the root to {@code this} node.
309         *
310         * @param node the node to test as descendant of this node
311         * @return {@code true} if this node is an ancestor of the given {@code node}
312         * @throws NullPointerException if the given {@code node} is {@code null}
313         */
314        default boolean isDescendant(final Tree<?, ?> node) {
315                return requireNonNull(node).isAncestor(this);
316        }
317
318        /**
319         * Returns the nearest common ancestor to this node and the given {@code node}.
320         * A node is considered an ancestor of itself.
321         *
322         * @param node {@code node} to find common ancestor with
323         * @return nearest ancestor common to this node and the given {@code node},
324         *         or {@link Optional#empty()} if no common ancestor exists.
325         * @throws NullPointerException if the given {@code node} is {@code null}
326         */
327        default Optional<T> sharedAncestor(final T node) {
328                requireNonNull(node);
329
330                T ancestor = null;
331                if (node.identical(this)) {
332                        ancestor = self();
333                } else {
334                        final int level1 = level();
335                        final int level2 = node.level();
336
337                        T node1;
338                        T node2;
339                        int diff;
340                        if (level2 > level1) {
341                                diff = level2 - level1;
342                                node1 = node;
343                                node2 = self();
344                        } else {
345                                diff = level1 - level2;
346                                node1 = self();
347                                node2 = node;
348                        }
349
350                        while (diff > 0 && node1 != null) {
351                                node1 = node1.parent().orElse(null);
352                                --diff;
353                        }
354
355                        do {
356                                if (node1 != null && node1.identical(node2)) {
357                                        ancestor = node1;
358                                }
359                                node1 = node1 != null
360                                        ? node1.parent().orElse(null)
361                                        : null;
362                                node2 = node2.parent().orElse(null);
363                        } while (node1 != null && node2 != null && ancestor == null);
364                }
365
366                return Optional.ofNullable(ancestor);
367        }
368
369        /**
370         * Returns true if and only if the given {@code node} is in the same tree as
371         * {@code this} node.
372         *
373         * @param node the other node to check
374         * @return true if the given {@code node} is in the same tree as {@code this}
375         *         node, {@code false} otherwise.
376         * @throws NullPointerException if the given {@code node} is {@code null}
377         */
378        default boolean isRelated(final Tree<?, ?> node) {
379                requireNonNull(node);
380                return node.root().identical(root());
381        }
382
383        /**
384         * Returns the path from the root, to get to this node. The last element in
385         * the path is this node.
386         *
387         * @since 5.1
388         *
389         * @return an array of TreeNode objects giving the path, where the
390         *         first element in the path is the root and the last
391         *         element is this node.
392         */
393        default ISeq<T> pathElements() {
394                return Trees.pathElementsFromRoot(self(), 0).toISeq();
395        }
396
397        /**
398         * Return the {@link Path} of {@code this} tree, such that
399         * <pre>{@code
400         * final Tree<Integer, ?> tree = ...;
401         * final Tree.Path path = tree.path();
402         * assert tree == tree.getRoot()
403         *     .childAtPath(path)
404         *     .orElse(null);
405         * }</pre>
406         *
407         * @since 5.1
408         *
409         * @return the path from the root element to {@code this} node.
410         */
411        default Path path() {
412                final int[] p = Trees.pathFromRoot(self(), 0);
413                return Path.of(p);
414        }
415
416        /**
417         * Returns the root of the tree that contains this node. The root is the
418         * ancestor with no parent.
419         *
420         * @return the root of the tree that contains this node
421         */
422        default T root() {
423                T anc = self();
424                T prev;
425
426                do {
427                        prev = anc;
428                        anc = anc.parent().orElse(null);
429                } while (anc != null);
430
431                return prev;
432        }
433
434        /* *************************************************************************
435         * Child query operations
436         **************************************************************************/
437
438        /**
439         * Return {@code true} if the given {@code node} is a child of {@code this}
440         * node.
441         *
442         * @param node the other node to check
443         * @return {@code true} if {@code node}is a child, {@code false} otherwise
444         * @throws NullPointerException if the given {@code node} is {@code null}
445         */
446        default boolean isChild(final Tree<?, ?> node) {
447                requireNonNull(node);
448                return childCount() != 0 &&
449                        node.parent().equals(Optional.of(self()));
450        }
451
452        /**
453         * Return the first child of {@code this} node, or {@code Optional.empty()}
454         * if {@code this} node has no children.
455         *
456         * @return the first child of this node
457         */
458        default Optional<T> firstChild() {
459                return childCount() > 0
460                        ? Optional.of(childAt(0))
461                        : Optional.empty();
462        }
463
464        /**
465         * Return the last child of {@code this} node, or {@code Optional.empty()}
466         * if {@code this} node has no children.
467         *
468         * @return the last child of this node
469         */
470        default Optional<T> lastChild() {
471                return childCount() > 0
472                        ? Optional.of(childAt(childCount() - 1))
473                        : Optional.empty();
474        }
475
476        /**
477         * Return the child which comes immediately after {@code this} node. This
478         * method performs a linear search of this node's children for {@code child}
479         * and is {@code O(n)} where n is the number of children.
480         *
481         * @param child the child node
482         * @return  the child of this node that immediately follows the {@code child},
483         *          or {@code Optional.empty()} if the given {@code node} is the
484         *          first node.
485         * @throws NullPointerException if the given {@code child} is {@code null}
486         */
487        default Optional<T> childAfter(final Tree<?, ?> child) {
488                requireNonNull(child);
489
490                final int index = indexOf(child);
491                if (index == -1) {
492                        throw new IllegalArgumentException("The given node is not a child.");
493                }
494
495                return index < childCount() - 1
496                        ? Optional.of(childAt(index + 1))
497                        : Optional.empty();
498        }
499
500        /**
501         * Return the child which comes immediately before {@code this} node. This
502         * method performs a linear search of this node's children for {@code child}
503         * and is {@code O(n)} where n is the number of children.
504         *
505         * @param child the child node
506         * @return  the child of this node that immediately precedes the {@code child},
507         *          or {@code null} if the given {@code node} is the first node.
508         * @throws NullPointerException if the given {@code child} is {@code null}
509         */
510        default Optional<T> childBefore(final Tree<?, ?> child) {
511                requireNonNull(child);
512
513                final int index = indexOf(child);
514                if (index == -1) {
515                        throw new IllegalArgumentException("The given node is not a child.");
516                }
517
518                return index > 0
519                        ? Optional.of(childAt(index - 1))
520                        : Optional.empty();
521        }
522
523        /**
524         * Return the node that follows {@code this} node in a pre-order traversal
525         * of {@code this} tree node. Return {@code Optional.empty()} if this node
526         * is the last node of the traversal. This is an inefficient way to traverse
527         * the entire tree use an iterator instead.
528         *
529         * @see #preorderIterator
530         * @return the node that follows this node in a pre-order traversal, or
531         *        {@code Optional.empty()} if this node is last
532         */
533        default Optional<T> nextNode() {
534                Optional<T> next = Optional.empty();
535
536                if (childCount() == 0) {
537                        T node = self();
538                        while (node != null && (next = node.nextSibling()).isEmpty()) {
539                                node = node.parent().orElse(null);
540                        }
541                } else {
542                        next = Optional.of(childAt(0));
543                }
544
545                return next;
546        }
547
548        /**
549         * Return the node that precedes this node in a pre-order traversal of
550         * {@code this} tree node. Returns {@code Optional.empty()} if this node is
551         * the first node of the traversal, the root of the tree. This is an
552         * inefficient way to traverse the entire tree; use an iterator instead.
553         *
554         * @see #preorderIterator
555         * @return the node that precedes this node in a pre-order traversal, or
556         *         {@code Optional.empty()} if this node is the first
557         */
558        default Optional<T> previousNode() {
559                Optional<T> node = Optional.empty();
560
561                if (parent().isPresent()) {
562                        final Optional<T> prev = previousSibling();
563                        if (prev.isPresent()) {
564                                node = prev.get().childCount() == 0
565                                        ? prev
566                                        : prev.map(Tree::lastLeaf);
567                        } else {
568                                node = parent();
569                        }
570                }
571
572                return node;
573        }
574
575        /* *************************************************************************
576         * Sibling query operations
577         **************************************************************************/
578
579        /**
580         * Test if the given {@code node} is a sibling of {@code this} node.
581         *
582         * @param node node to test as sibling of this node
583         * @return {@code true} if the {@code node} is a sibling of {@code this}
584         *         node
585         * @throws NullPointerException if the given {@code node} is {@code null}
586         */
587        default boolean isSibling(final Tree<?, ?> node) {
588                return identical(requireNonNull(node)) ||
589                        parent().equals(node.parent());
590        }
591
592        /**
593         * Return the number of siblings of {@code this} node. A node is its own
594         * sibling (if it has no parent or no siblings, this method returns
595         * {@code 1}).
596         *
597         * @return the number of siblings of {@code this} node
598         */
599        default int siblingCount() {
600                return parent().map(Tree::childCount).orElse(1);
601        }
602
603        /**
604         * Return the next sibling of {@code this} node in the parent's children
605         * array, or {@code null} if {@code this} node has no parent or it is the
606         * last child of the paren. This method performs a linear search that is
607         * {@code O(n)} where n is the number of children; to traverse the entire
608         * array, use the iterator of the parent instead.
609         *
610         * @see #childStream()
611         * @return the sibling of {@code this} node that immediately follows
612         *         {@code this} node
613         */
614        default Optional<T> nextSibling() {
615                return parent().flatMap(p -> p.childAfter(self()));
616        }
617
618        /**
619         * Return the previous sibling of {@code this} node in the parent's children
620         * list, or {@code Optional.empty()} if this node has no parent or is the
621         * parent's first child. This method performs a linear search that is O(n)
622         * where n is the number of children.
623         *
624         * @return the sibling of {@code this} node that immediately precedes this
625         *         node
626         */
627        default Optional<T> previousSibling() {
628                return parent().flatMap(p -> p.childBefore(self()));
629        }
630
631
632        /* *************************************************************************
633         * Leaf query operations
634         **************************************************************************/
635
636        /**
637         * Return {@code true} if {@code this} node has no children.
638         *
639         * @return {@code true} if {@code this} node has no children, {@code false}
640         *         otherwise
641         */
642        default boolean isLeaf() {
643                return childCount() == 0;
644        }
645
646        /**
647         * Return the first leaf that is a descendant of {@code this} node; either
648         * this node or its first child's first leaf. {@code this} node is returned
649         * if it is a leaf.
650         *
651         * @see #isLeaf
652         * @see  #isDescendant
653         * @return the first leaf in the subtree rooted at this node
654         */
655        default T firstLeaf() {
656                T leaf = self();
657                while (!leaf.isLeaf()) {
658                        leaf = leaf.firstChild().orElseThrow(AssertionError::new);
659                }
660
661                return leaf;
662        }
663
664        /**
665         * Return the last leaf that is a descendant of this node; either
666         * {@code this} node or its last child's last leaf. Returns {@code this}
667         * node if it is a leaf.
668         *
669         * @see #isLeaf
670         * @see #isDescendant
671         * @return the last leaf in this subtree
672         */
673        default T lastLeaf() {
674                T leaf = self();
675                while (!leaf.isLeaf()) {
676                        leaf = leaf.lastChild().orElseThrow(AssertionError::new);
677                }
678
679                return leaf;
680        }
681
682        /**
683         * Returns the leaf after {@code this} node or {@code Optional.empty()} if
684         * this node is the last leaf in the tree.
685         * <p>
686         * In order to determine the next node, this method first performs a linear
687         * search in the parent's child-list in order to find the current node.
688         * <p>
689         * That implementation makes the operation suitable for short traversals
690         * from a known position. But to traverse all the leaves in the tree, you
691         * should use {@link #depthFirstIterator()} to iterator the nodes in the
692         * tree and use {@link #isLeaf()} on each node to determine which are leaves.
693         *
694         * @see #depthFirstIterator
695         * @see #isLeaf
696         * @return return the next leaf past this node
697         */
698        default Optional<T> nextLeaf() {
699                return nextSibling()
700                        .map(Tree::firstLeaf)
701                        .or(() -> parent().flatMap(Tree::nextLeaf));
702        }
703
704        /**
705         * Return the leaf before {@code this} node or {@code null} if {@code this}
706         * node is the first leaf in the tree.
707         * <p>
708         * In order to determine the previous node, this method first performs a
709         * linear search in the parent's child-list in order to find the current
710         * node.
711         * <p>
712         * That implementation makes the operation suitable for short traversals
713         * from a known position. But to traverse all the leaves in the tree, you
714         * should use {@link #depthFirstIterator()} to iterate the nodes in the tree
715         * and use {@link #isLeaf()} on each node to determine which are leaves.
716         *
717         * @see #depthFirstIterator
718         * @see #isLeaf
719         * @return returns the leaf before {@code this} node
720         */
721        default Optional<T> previousLeaf() {
722                return previousSibling()
723                        .map(Tree::lastLeaf)
724                        .or(() -> parent().flatMap(Tree::previousLeaf));
725        }
726
727        /**
728         * Returns the total number of leaves that are descendants of this node.
729         * If this node is a leaf, returns {@code 1}. This method is {@code O(n)},
730         * where n is the number of descendants of {@code this} node.
731         *
732         * @see #isLeaf()
733         * @return the number of leaves beneath this node
734         */
735        default int leafCount() {
736                return (int)leaves().count();
737        }
738
739        /**
740         * Return a stream of leaves that are descendants of this node.
741         *
742         * @since 7.0
743         *
744         * @return a stream of leaves that are descendants of this node
745         */
746        default Stream<T> leaves() {
747                return breadthFirstStream().filter(Tree::isLeaf);
748        }
749
750        /* *************************************************************************
751         * Tree traversing.
752         **************************************************************************/
753
754        /**
755         * Return an iterator that traverses the subtree rooted at {@code this}
756         * node in breadth-first order. The first node returned by the iterator is
757         * {@code this} node.
758         * <p>
759         * Modifying the tree by inserting, removing, or moving a node invalidates
760         * any iterator created before the modification.
761         *
762         * @see #depthFirstIterator
763         * @return an iterator for traversing the tree in breadth-first order
764         */
765        default Iterator<T> breadthFirstIterator() {
766                return new TreeNodeBreadthFirstIterator<>(self());
767        }
768
769        /**
770         * Return an iterator that traverses the subtree rooted at {@code this}.
771         * The first node returned by the iterator is {@code this} node.
772         * <p>
773         * Modifying the tree by inserting, removing, or moving a node invalidates
774         * any iterator created before the modification.
775         *
776         * @see #breadthFirstIterator
777         * @return an iterator for traversing the tree in breadth-first order
778         */
779        @Override
780        default Iterator<T> iterator() {
781                return breadthFirstIterator();
782        }
783
784        /**
785         * Return a stream that traverses the subtree rooted at {@code this} node in
786         * breadth-first order. The first node returned by the stream is
787         * {@code this} node.
788         *
789         * @see #depthFirstIterator
790         * @see #stream()
791         * @return a stream for traversing the tree in breadth-first order
792         */
793        default Stream<T> breadthFirstStream() {
794                return StreamSupport
795                        .stream(spliteratorUnknownSize(breadthFirstIterator(), 0), false);
796        }
797
798        /**
799         * Return a stream that traverses the subtree rooted at {@code this} node in
800         * breadth-first order. The first node returned by the stream is
801         * {@code this} node.
802         *
803         * @see #breadthFirstStream
804         * @return a stream for traversing the tree in breadth-first order
805         */
806        default Stream<T> stream() {
807                return breadthFirstStream();
808        }
809
810        /**
811         * Return an iterator that traverses the subtree rooted at {@code this} node
812         * in pre-order. The first node returned by the iterator is {@code this}
813         * node.
814         * <p>
815         * Modifying the tree by inserting, removing, or moving a node invalidates
816         * any iterator created before the modification.
817         *
818         * @see #postorderIterator
819         * @return an iterator for traversing the tree in pre-order
820         */
821        default Iterator<T> preorderIterator() {
822                return new TreeNodePreorderIterator<>(self());
823        }
824
825        /**
826         * Return a stream that traverses the subtree rooted at {@code this} node
827         * in pre-order. The first node returned by the stream is {@code this} node.
828         * <p>
829         * Modifying the tree by inserting, removing, or moving a node invalidates
830         * any iterator created before the modification.
831         *
832         * @see #preorderIterator
833         * @return a stream for traversing the tree in pre-order
834         */
835        default Stream<T> preorderStream() {
836                return StreamSupport
837                        .stream(spliteratorUnknownSize(preorderIterator(), 0), false);
838        }
839
840        /**
841         * Return an iterator that traverses the subtree rooted at {@code this}
842         * node in post-order. The first node returned by the iterator is the
843         * leftmost leaf.  This is the same as a depth-first traversal.
844         *
845         * @see #depthFirstIterator
846         * @see #preorderIterator
847         * @return an iterator for traversing the tree in post-order
848         */
849        default Iterator<T> postorderIterator() {
850                return new TreeNodePostorderIterator<>(self());
851        }
852
853        /**
854         * Return a stream that traverses the subtree rooted at {@code this} node in
855         * post-order. The first node returned by the iterator is the leftmost leaf.
856         * This is the same as a depth-first traversal.
857         *
858         * @see #depthFirstIterator
859         * @see #preorderIterator
860         * @return a stream for traversing the tree in post-order
861         */
862        default Stream<T> postorderStream() {
863                return StreamSupport
864                        .stream(spliteratorUnknownSize(postorderIterator(), 0), false);
865        }
866
867        /**
868         * Return an iterator that traverses the subtree rooted at {@code this} node
869         * in depth-first order. The first node returned by the iterator is the
870         * leftmost leaf. This is the same as a postorder traversal.
871         * <p>
872         * Modifying the tree by inserting, removing, or moving a node invalidates
873         * any iterator created before the modification.
874         *
875         * @see #breadthFirstIterator
876         * @see #postorderIterator
877         * @return an iterator for traversing the tree in depth-first order
878         */
879        default Iterator<T> depthFirstIterator() {
880                return postorderIterator();
881        }
882
883        /**
884         * Return a stream that traverses the subtree rooted at {@code this} node in
885         * depth-first. The first node returned by the iterator is the leftmost leaf.
886         * This is the same as a post-order traversal.
887         *
888         * @see #depthFirstIterator
889         * @see #preorderIterator
890         * @return a stream for traversing the tree in post-order
891         */
892        default Stream<T> depthFirstStream() {
893                return postorderStream();
894        }
895
896        /**
897         * Return an iterator that follows the path from {@code ancestor} to
898         * {@code this} node. The iterator return {@code ancestor} as first element,
899         * The creation of the iterator is O(m), where m is the number of nodes
900         * between {@code this} node and the {@code ancestor}, inclusive.
901         * <p>
902         * Modifying the tree by inserting, removing, or moving a node invalidates
903         * any iterator created before the modification.
904         *
905         * @see #isAncestor
906         * @see #isDescendant
907         * @param ancestor the ancestor node
908         * @return an iterator for following the path from an ancestor of {@code this}
909         *         node to this one
910         * @throws IllegalArgumentException if the {@code ancestor} is not an
911         *         ancestor of this node
912         * @throws NullPointerException if the given {@code ancestor} is {@code null}
913         */
914        default Iterator<T> pathFromAncestorIterator(final Tree<?, ?> ancestor) {
915                return new TreeNodePathIterator<>(ancestor, self());
916        }
917
918        /**
919         * Return the path of {@code this} child node from the root node. You will
920         * get {@code this} node, if you call {@link #childAtPath(Path)} on the
921         * root node of {@code this} node.
922         * <pre>{@code
923         * final Tree<?, ?> node = ...;
924         * final Tree<?, ?> root = node.getRoot();
925         * final int[] path = node.childPath();
926         * assert node == root.childAtPath(path);
927         * }</pre>
928         *
929         * @since 4.4
930         *
931         * @see #childAtPath(Path)
932         *
933         * @return the path of {@code this} child node from the root node.
934         */
935        default Path childPath() {
936                final Iterator<T> it = pathFromAncestorIterator(root());
937                final int[] path = new int[level()];
938
939                T tree = null;
940                int index = 0;
941                while (it.hasNext()) {
942                        final T child = it.next();
943                        if (tree != null) {
944                                path[index++] = tree.indexOf(child);
945                        }
946
947                        tree = child;
948                }
949
950                assert index == path.length;
951
952                return new Path(path);
953        }
954
955        /**
956         * Tests whether {@code this} node is the same as the {@code other} node.
957         * The default implementation returns the object identity,
958         * {@code this == other}, of the two objects, but other implementations may
959         * use different criteria for checking the <i>identity</i>.
960         *
961         * @param other the {@code other} node
962         * @return {@code true} if the {@code other} node is the same as {@code this}
963         *         node.
964         */
965        default boolean identical(final Tree<?, ?> other) {
966                return this == other;
967        }
968
969        /* *************************************************************************
970         * 'toString' methods
971         **************************************************************************/
972
973        /**
974         * Return a compact string representation of the given tree. The tree
975         * <pre>
976         *  mul
977         *  ├── div
978         *  │   ├── cos
979         *  │   │   └── 1.0
980         *  │   └── cos
981         *  │       └── π
982         *  └── sin
983         *      └── mul
984         *          ├── 1.0
985         *          └── z
986         *  </pre>
987         * is printed as
988         * <pre>
989         *  mul(div(cos(1.0),cos(π)),sin(mul(1.0,z)))
990         * </pre>
991         *
992         * @since 4.3
993         *
994         * @see #toParenthesesString()
995         * @see TreeFormatter#PARENTHESES
996         *
997         * @param mapper the {@code mapper} which converts the tree value to a string
998         * @return the string representation of the given tree
999         */
1000        default String toParenthesesString(final Function<? super V, String> mapper) {
1001                return TreeFormatter.PARENTHESES.format(this, mapper);
1002        }
1003
1004        /**
1005         * Return a compact string representation of the given tree. The tree
1006         * <pre>
1007         *  mul
1008         *  ├── div
1009         *  │   ├── cos
1010         *  │   │   └── 1.0
1011         *  │   └── cos
1012         *  │       └── π
1013         *  └── sin
1014         *      └── mul
1015         *          ├── 1.0
1016         *          └── z
1017         *  </pre>
1018         * is printed as
1019         * <pre>
1020         *  mul(div(cos(1.0), cos(π)), sin(mul(1.0, z)))
1021         * </pre>
1022         *
1023         * @since 4.3
1024         *
1025         * @see #toParenthesesString(Function)
1026         * @see TreeFormatter#PARENTHESES
1027         *
1028         * @return the string representation of the given tree
1029         * @throws NullPointerException if the {@code mapper} is {@code null}
1030         */
1031        default String toParenthesesString() {
1032                return toParenthesesString(Objects::toString);
1033        }
1034
1035        /* *************************************************************************
1036         * Static helper methods.
1037         **************************************************************************/
1038
1039        /**
1040         * Calculates the hash code of the given tree.
1041         *
1042         * @param tree the tree where the hash is calculated from
1043         * @return the hash code of the tree
1044         * @throws NullPointerException if the given {@code tree} is {@code null}
1045         */
1046        static int hashCode(final Tree<?, ?> tree) {
1047                return tree != null
1048                        ? tree.breadthFirstStream()
1049                                .mapToInt(node -> 31*Objects.hashCode(node.value()) + 37)
1050                                .sum() + 17
1051                        : 0;
1052        }
1053
1054        /**
1055         * Checks if the two given trees has the same structure with the same values.
1056         *
1057         * @param a the first tree
1058         * @param b the second tree
1059         * @return {@code true} if the two given trees are structurally equals,
1060         *         {@code false} otherwise
1061         */
1062        static boolean equals(final Tree<?, ?> a, final Tree<?, ?> b) {
1063                return Trees.equals(a, b);
1064        }
1065
1066        /**
1067         * Return a string representation of the given tree, like the following
1068         * example.
1069         *
1070         * <pre>
1071         *  mul(div(cos(1.0), cos(π)), sin(mul(1.0, z)))
1072         * </pre>
1073         *
1074         * This method is intended to be used when override the
1075         * {@link Object#toString()} method.
1076         *
1077         * @param tree the input tree
1078         * @return the string representation of the given tree
1079         */
1080        static String toString(final Tree<?, ?> tree) {
1081                return tree.toParenthesesString();
1082        }
1083
1084
1085        /* *************************************************************************
1086         * Inner classes
1087         **************************************************************************/
1088
1089        /**
1090         * This class represents the path to child within a given tree. It allows
1091         * pointing (and fetch) a tree child.
1092         *
1093         * @see Tree#childAtPath(Path)
1094         *
1095         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
1096         * @version 6.0
1097         * @since 4.4
1098         */
1099        final class Path implements Serializable {
1100
1101                @Serial
1102                private static final long serialVersionUID = 1L;
1103
1104                private final int[] _path;
1105
1106                private Path(final int[] path) {
1107                        _path = requireNonNull(path);
1108                }
1109
1110                /**
1111                 * Return the path length, which is the level of the child {@code this}
1112                 * path points to.
1113                 *
1114                 * @return the path length
1115                 */
1116                public int length() {
1117                        return _path.length;
1118                }
1119
1120                /**
1121                 * Return the child index at the given index (child level).
1122                 *
1123                 * @param index the path index
1124                 * @return the child index at the given child level
1125                 * @throws IndexOutOfBoundsException if the index is not with the range
1126                 *         {@code [0, length())}
1127                 */
1128                public int get(final int index) {
1129                        return _path[index];
1130                }
1131
1132                /**
1133                 * Return the path as {@code int[]} array.
1134                 *
1135                 * @return the path as {@code int[]} array
1136                 */
1137                public int[] toArray() {
1138                        return _path.clone();
1139                }
1140
1141                /**
1142                 * Appends the given {@code path} to {@code this} one.
1143                 *
1144                 * @param path the path to append
1145                 * @return a new {@code Path} with the given {@code path} appended
1146                 * @throws NullPointerException if the given {@code path} is {@code null}
1147                 */
1148                public Path append(final Path path) {
1149                        final int[] p = new int[length() + path.length()];
1150                        System.arraycopy(_path, 0, p, 0, length());
1151                        System.arraycopy(path._path, 0, p, length(), path.length());
1152                        return new Path(p);
1153                }
1154
1155                @Override
1156                public int hashCode() {
1157                        return Arrays.hashCode(_path);
1158                }
1159
1160                @Override
1161                public boolean equals(final Object obj) {
1162                        return obj == this ||
1163                                obj instanceof Path other &&
1164                                Arrays.equals(_path, other._path);
1165                }
1166
1167                @Override
1168                public String toString() {
1169                        return Arrays.toString(_path);
1170                }
1171
1172                /**
1173                 * Create a new path object from the given child indexes.
1174                 *
1175                 * @param path the child indexes
1176                 * @return a new tree path
1177                 * @throws IllegalArgumentException if one of the path elements is
1178                 *         smaller than zero
1179                 */
1180                public static Path of(final int... path) {
1181                        for (int i = 0; i < path.length; ++i) {
1182                                if (path[i] < 0) {
1183                                        throw new IllegalArgumentException(format(
1184                                                "Path element at position %d is smaller than zero: %d",
1185                                                i, path[i]
1186                                        ));
1187                                }
1188                        }
1189
1190                        return new Path(path.clone());
1191                }
1192
1193
1194                /* *********************************************************************
1195                 *  Java object serialization
1196                 * ********************************************************************/
1197
1198                @Serial
1199                private Object writeReplace() {
1200                        return new SerialProxy(SerialProxy.TREE_PATH, this);
1201                }
1202
1203                @Serial
1204                private void readObject(final ObjectInputStream stream)
1205                        throws InvalidObjectException
1206                {
1207                        throw new InvalidObjectException("Serialization proxy required.");
1208                }
1209
1210
1211                void write(final DataOutput out) throws IOException {
1212                        writeIntArray(_path, out);
1213                }
1214
1215                static Object read(final DataInput in) throws IOException {
1216                        return Path.of(readIntArray(in));
1217                }
1218
1219        }
1220
1221}