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