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