0001 /*
0002 * Java Genetic Algorithm Library (jenetics-7.1.2).
0003 * Copyright (c) 2007-2023 Franz Wilhelmstötter
0004 *
0005 * Licensed under the Apache License, Version 2.0 (the "License");
0006 * you may not use this file except in compliance with the License.
0007 * You may obtain a copy of the License at
0008 *
0009 * http://www.apache.org/licenses/LICENSE-2.0
0010 *
0011 * Unless required by applicable law or agreed to in writing, software
0012 * distributed under the License is distributed on an "AS IS" BASIS,
0013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014 * See the License for the specific language governing permissions and
0015 * limitations under the License.
0016 *
0017 * Author:
0018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
0019 */
0020 package io.jenetics.ext.util;
0021
0022 import static java.lang.String.format;
0023 import static java.util.Objects.requireNonNull;
0024 import static java.util.Spliterators.spliteratorUnknownSize;
0025 import static io.jenetics.internal.util.SerialIO.readIntArray;
0026 import static io.jenetics.internal.util.SerialIO.writeIntArray;
0027
0028 import java.io.DataInput;
0029 import java.io.DataOutput;
0030 import java.io.IOException;
0031 import java.io.InvalidObjectException;
0032 import java.io.ObjectInputStream;
0033 import java.io.Serial;
0034 import java.io.Serializable;
0035 import java.lang.reflect.Array;
0036 import java.util.Arrays;
0037 import java.util.Iterator;
0038 import java.util.Objects;
0039 import java.util.Optional;
0040 import java.util.Spliterator;
0041 import java.util.Spliterators;
0042 import java.util.function.BiFunction;
0043 import java.util.function.Function;
0044 import java.util.stream.Stream;
0045 import java.util.stream.StreamSupport;
0046
0047 import io.jenetics.util.ISeq;
0048 import io.jenetics.util.Self;
0049
0050 /**
0051 * General purpose tree structure. The interface only contains tree read methods.
0052 * For a mutable tree implementation have a look at the {@link TreeNode} class.
0053 *
0054 * @see TreeNode
0055 *
0056 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0057 * @version 7.0
0058 * @since 3.9
0059 */
0060 public interface Tree<V, T extends Tree<V, T>> extends Self<T>, Iterable<T> {
0061
0062 /* *************************************************************************
0063 * Basic (abstract) operations. All other tree operations can be derived
0064 * from these methods.
0065 **************************************************************************/
0066
0067 /**
0068 * Return the value of the current {@code Tree} node. The value may be
0069 * {@code null}.
0070 *
0071 * @return the value of the current {@code Tree} node
0072 */
0073 V value();
0074
0075 /**
0076 * Return the <em>parent</em> node of this tree node.
0077 *
0078 * @return the parent node, or {@code Optional.empty()} if this node is the
0079 * root of the tree
0080 */
0081 Optional<T> parent();
0082
0083 /**
0084 * Return the child node with the given index.
0085 *
0086 * @param index the child index
0087 * @return the child node with the given index
0088 * @throws IndexOutOfBoundsException if the {@code index} is out of
0089 * bounds ({@code [0, childCount())})
0090 */
0091 T childAt(final int index);
0092
0093 /**
0094 * Return the number of children this tree node consists of.
0095 *
0096 * @return the number of children this tree node consists of
0097 */
0098 int childCount();
0099
0100
0101 /* *************************************************************************
0102 * Derived operations
0103 **************************************************************************/
0104
0105 /**
0106 * Return an iterator of the children of this {@code Tree} node.
0107 *
0108 * @return an iterator of the children of this {@code Tree} node.
0109 */
0110 default Iterator<T> childIterator() {
0111 return new TreeChildIterator<V, T>(self());
0112 }
0113
0114 /**
0115 * Return a forward-order stream of this node's children.
0116 *
0117 * @return a stream of children of {@code this} node
0118 */
0119 default Stream<T> childStream() {
0120 return StreamSupport.stream(
0121 Spliterators.spliterator(
0122 childIterator(),
0123 childCount(),
0124 Spliterator.SIZED | Spliterator.ORDERED
0125 ),
0126 false
0127 );
0128 }
0129
0130 /**
0131 * Returns {@code true} if this node is the root of the tree.
0132 *
0133 * @return {@code true} if this node is the root of its tree, {@code false}
0134 * otherwise
0135 */
0136 default boolean isRoot() {
0137 return parent().isEmpty();
0138 }
0139
0140 /**
0141 * Returns the depth of the tree rooted at this node. The <i>depth</i> of a
0142 * tree is the longest distance from {@code this} node to a leaf. If
0143 * {@code this} node has no children, 0 is returned. This operation is much
0144 * more expensive than {@link #level()} because it must effectively traverse
0145 * the entire tree rooted at {@code this} node.
0146 *
0147 * @return the depth of the tree whose root is this node
0148 */
0149 default int depth() {
0150 final Iterator<T> it = breadthFirstIterator();
0151
0152 T last = null;
0153 while (it.hasNext()) {
0154 last = it.next();
0155 }
0156
0157 assert last != null;
0158 return last.level() - level();
0159 }
0160
0161 /**
0162 * Returns the number of levels above this node. The <i>level</i> of a tree
0163 * is the distance from the root to {@code this} node. If {@code this} node
0164 * is the root, returns 0.
0165 *
0166 * @return the number of levels above this node
0167 */
0168 default int level() {
0169 Optional<T> ancestor = Optional.of(self());
0170 int levels = 0;
0171 while ((ancestor = ancestor.flatMap(Tree::parent)).isPresent()) {
0172 ++levels;
0173 }
0174
0175 return levels;
0176 }
0177
0178 /**
0179 * Returns the index of the specified child in this node's child array, or
0180 * {@code -1} if {@code this} node doesn't contain the given {@code child}.
0181 * This method performs a linear search and is O(n) where {@code n} is the
0182 * number of children.
0183 *
0184 * @param child the TreeNode to search for among this node's children
0185 * @throws NullPointerException if the given {@code child} is {@code null}
0186 * @return the index of the node in this node's child array, or {@code -1}
0187 * if the node could not be found
0188 */
0189 default int indexOf(final Tree<?, ?> child) {
0190 int index = -1;
0191 for (int i = 0, n = childCount(); i < n && index == -1; ++i) {
0192 if (childAt(i).identical(child)) {
0193 index = i;
0194 }
0195 }
0196
0197 return index;
0198 }
0199
0200 /**
0201 * Return the number of nodes of {@code this} node (sub-tree).
0202 *
0203 * @return the number of nodes of {@code this} node (sub-tree)
0204 */
0205 default int size() {
0206 return Trees.countChildren(this) + 1;
0207 }
0208
0209 /**
0210 * A tree is considered <em>empty</em> if it's {@link #value()} is
0211 * {@code null} and has no children and parent. A newly created tree node
0212 * with no value is <em>empty</em>.
0213 *
0214 * <pre>{@code
0215 * final Tree<String, ?> tree = TreeNode.of();
0216 * assert tree.isEmpty();
0217 * }</pre>
0218 *
0219 * @since 7.0
0220 *
0221 * @return {@code true} if {@code this} tree is empty, {@code false}
0222 * otherwise
0223 */
0224 default boolean isEmpty() {
0225 return value() == null && childCount() == 0 && parent().isEmpty();
0226 }
0227
0228
0229 /* *************************************************************************
0230 * Query operations
0231 **************************************************************************/
0232
0233 /**
0234 * Return the child node at the given {@code path}. A path consists of the
0235 * child index at a give level, starting with level 1. (The root note has
0236 * level zero.) {@code tree.childAtPath(Path.of(2))} will return the third
0237 * child node of {@code this} node, if it exists and
0238 * {@code tree.childAtPath(Path.of(2, 0))} will return the first child of
0239 * the third child of {@code this node}.
0240 *
0241 * @since 4.4
0242 *
0243 * @see #childAtPath(int...)
0244 *
0245 * @param path the child path
0246 * @return the child node at the given {@code path}
0247 * @throws NullPointerException if the given {@code path} array is
0248 * {@code null}
0249 */
0250 default Optional<T> childAtPath(final Path path) {
0251 T node = self();
0252 for (int i = 0; i < path.length() && node != null; ++i) {
0253 node = path.get(i) < node.childCount()
0254 ? node.childAt(path.get(i))
0255 : null;
0256 }
0257
0258 return Optional.ofNullable(node);
0259 }
0260
0261 /**
0262 * Return the child node at the given {@code path}. A path consists of the
0263 * child index at a give level, starting with level 1. (The root note has
0264 * level zero.) {@code tree.childAtPath(2)} will return the third child node
0265 * of {@code this} node, if it exists and {@code tree.childAtPath(2, 0)} will
0266 * return the first child of the third child of {@code this node}.
0267 *
0268 * @since 4.3
0269 *
0270 * @see #childAtPath(Path)
0271 *
0272 * @param path the child path
0273 * @return the child node at the given {@code path}
0274 * @throws NullPointerException if the given {@code path} array is
0275 * {@code null}
0276 * @throws IllegalArgumentException if one of the path elements is smaller
0277 * than zero
0278 */
0279 default Optional<T> childAtPath(final int... path) {
0280 return childAtPath(Path.of(path));
0281 }
0282
0283 /**
0284 * Return {@code true} if the given {@code node} is an ancestor of
0285 * {@code this} node. This operation is at worst {@code O(h)} where {@code h}
0286 * is the distance from the root to {@code this} node.
0287 *
0288 * @param node the node to test
0289 * @return {@code true} if the given {@code node} is an ancestor of
0290 * {@code this} node, {@code false} otherwise
0291 * @throws NullPointerException if the given {@code node} is {@code null}
0292 */
0293 default boolean isAncestor(final Tree<?, ?> node) {
0294 requireNonNull(node);
0295
0296 Optional<T> ancestor = Optional.of(self());
0297 boolean result;
0298 do {
0299 result = ancestor.filter(a -> a.identical(node)).isPresent();
0300 } while (!result &&
0301 (ancestor = ancestor.flatMap(Tree::parent)).isPresent());
0302
0303 return result;
0304 }
0305
0306 /**
0307 * Return {@code true} if the given {@code node} is a descendant of
0308 * {@code this} node. If the given {@code node} is {@code null},
0309 * {@code false} is returned. This operation is at worst {@code O(h)} where
0310 * {@code h} is the distance from the root to {@code this} node.
0311 *
0312 * @param node the node to test as descendant of this node
0313 * @return {@code true} if this node is an ancestor of the given {@code node}
0314 * @throws NullPointerException if the given {@code node} is {@code null}
0315 */
0316 default boolean isDescendant(final Tree<?, ?> node) {
0317 return requireNonNull(node).isAncestor(this);
0318 }
0319
0320 /**
0321 * Returns the nearest common ancestor to this node and the given {@code node}.
0322 * A node is considered an ancestor of itself.
0323 *
0324 * @param node {@code node} to find common ancestor with
0325 * @return nearest ancestor common to this node and the given {@code node},
0326 * or {@link Optional#empty()} if no common ancestor exists.
0327 * @throws NullPointerException if the given {@code node} is {@code null}
0328 */
0329 default Optional<T> sharedAncestor(final T node) {
0330 requireNonNull(node);
0331
0332 T ancestor = null;
0333 if (node.identical(this)) {
0334 ancestor = self();
0335 } else {
0336 final int level1 = level();
0337 final int level2 = node.level();
0338
0339 T node1;
0340 T node2;
0341 int diff;
0342 if (level2 > level1) {
0343 diff = level2 - level1;
0344 node1 = node;
0345 node2 = self();
0346 } else {
0347 diff = level1 - level2;
0348 node1 = self();
0349 node2 = node;
0350 }
0351
0352 while (diff > 0 && node1 != null) {
0353 node1 = node1.parent().orElse(null);
0354 --diff;
0355 }
0356
0357 do {
0358 if (node1 != null && node1.identical(node2)) {
0359 ancestor = node1;
0360 }
0361 node1 = node1 != null
0362 ? node1.parent().orElse(null)
0363 : null;
0364 node2 = node2.parent().orElse(null);
0365 } while (node1 != null && node2 != null && ancestor == null);
0366 }
0367
0368 return Optional.ofNullable(ancestor);
0369 }
0370
0371 /**
0372 * Returns true if and only if the given {@code node} is in the same tree as
0373 * {@code this} node.
0374 *
0375 * @param node the other node to check
0376 * @return true if the given {@code node} is in the same tree as {@code this}
0377 * node, {@code false} otherwise.
0378 * @throws NullPointerException if the given {@code node} is {@code null}
0379 */
0380 default boolean isRelated(final Tree<?, ?> node) {
0381 requireNonNull(node);
0382 return node.root().identical(root());
0383 }
0384
0385 /**
0386 * Returns the path from the root, to get to this node. The last element in
0387 * the path is this node.
0388 *
0389 * @since 5.1
0390 *
0391 * @return an array of TreeNode objects giving the path, where the
0392 * first element in the path is the root and the last
0393 * element is this node.
0394 */
0395 default ISeq<T> pathElements() {
0396 return Trees.pathElementsFromRoot(self(), 0).toISeq();
0397 }
0398
0399 /**
0400 * Return the {@link Path} of {@code this} tree, such that
0401 * <pre>{@code
0402 * final Tree<Integer, ?> tree = ...;
0403 * final Tree.Path path = tree.path();
0404 * assert tree == tree.getRoot()
0405 * .childAtPath(path)
0406 * .orElse(null);
0407 * }</pre>
0408 *
0409 * @since 5.1
0410 *
0411 * @return the path from the root element to {@code this} node.
0412 */
0413 default Path path() {
0414 final int[] p = Trees.pathFromRoot(self(), 0);
0415 return Path.of(p);
0416 }
0417
0418 /**
0419 * Returns the root of the tree that contains this node. The root is the
0420 * ancestor with no parent.
0421 *
0422 * @return the root of the tree that contains this node
0423 */
0424 default T root() {
0425 T anc = self();
0426 T prev;
0427
0428 do {
0429 prev = anc;
0430 anc = anc.parent().orElse(null);
0431 } while (anc != null);
0432
0433 return prev;
0434 }
0435
0436 /* *************************************************************************
0437 * Child query operations
0438 **************************************************************************/
0439
0440 /**
0441 * Return {@code true} if the given {@code node} is a child of {@code this}
0442 * node.
0443 *
0444 * @param node the other node to check
0445 * @return {@code true} if {@code node}is a child, {@code false} otherwise
0446 * @throws NullPointerException if the given {@code node} is {@code null}
0447 */
0448 default boolean isChild(final Tree<?, ?> node) {
0449 requireNonNull(node);
0450 return childCount() != 0 &&
0451 node.parent().equals(Optional.of(self()));
0452 }
0453
0454 /**
0455 * Return the first child of {@code this} node, or {@code Optional.empty()}
0456 * if {@code this} node has no children.
0457 *
0458 * @return the first child of this node
0459 */
0460 default Optional<T> firstChild() {
0461 return childCount() > 0
0462 ? Optional.of(childAt(0))
0463 : Optional.empty();
0464 }
0465
0466 /**
0467 * Return the last child of {@code this} node, or {@code Optional.empty()}
0468 * if {@code this} node has no children.
0469 *
0470 * @return the last child of this node
0471 */
0472 default Optional<T> lastChild() {
0473 return childCount() > 0
0474 ? Optional.of(childAt(childCount() - 1))
0475 : Optional.empty();
0476 }
0477
0478 /**
0479 * Return the child which comes immediately after {@code this} node. This
0480 * method performs a linear search of this node's children for {@code child}
0481 * and is {@code O(n)} where n is the number of children.
0482 *
0483 * @param child the child node
0484 * @return the child of this node that immediately follows the {@code child},
0485 * or {@code Optional.empty()} if the given {@code node} is the
0486 * first node.
0487 * @throws NullPointerException if the given {@code child} is {@code null}
0488 */
0489 default Optional<T> childAfter(final Tree<?, ?> child) {
0490 requireNonNull(child);
0491
0492 final int index = indexOf(child);
0493 if (index == -1) {
0494 throw new IllegalArgumentException("The given node is not a child.");
0495 }
0496
0497 return index < childCount() - 1
0498 ? Optional.of(childAt(index + 1))
0499 : Optional.empty();
0500 }
0501
0502 /**
0503 * Return the child which comes immediately before {@code this} node. This
0504 * method performs a linear search of this node's children for {@code child}
0505 * and is {@code O(n)} where n is the number of children.
0506 *
0507 * @param child the child node
0508 * @return the child of this node that immediately precedes the {@code child},
0509 * or {@code null} if the given {@code node} is the first node.
0510 * @throws NullPointerException if the given {@code child} is {@code null}
0511 */
0512 default Optional<T> childBefore(final Tree<?, ?> child) {
0513 requireNonNull(child);
0514
0515 final int index = indexOf(child);
0516 if (index == -1) {
0517 throw new IllegalArgumentException("The given node is not a child.");
0518 }
0519
0520 return index > 0
0521 ? Optional.of(childAt(index - 1))
0522 : Optional.empty();
0523 }
0524
0525 /**
0526 * Return the node that follows {@code this} node in a pre-order traversal
0527 * of {@code this} tree node. Return {@code Optional.empty()} if this node
0528 * is the last node of the traversal. This is an inefficient way to traverse
0529 * the entire tree use an iterator instead.
0530 *
0531 * @see #preorderIterator
0532 * @return the node that follows this node in a pre-order traversal, or
0533 * {@code Optional.empty()} if this node is last
0534 */
0535 default Optional<T> nextNode() {
0536 Optional<T> next = Optional.empty();
0537
0538 if (childCount() == 0) {
0539 T node = self();
0540 while (node != null && (next = node.nextSibling()).isEmpty()) {
0541 node = node.parent().orElse(null);
0542 }
0543 } else {
0544 next = Optional.of(childAt(0));
0545 }
0546
0547 return next;
0548 }
0549
0550 /**
0551 * Return the node that precedes this node in a pre-order traversal of
0552 * {@code this} tree node. Returns {@code Optional.empty()} if this node is
0553 * the first node of the traversal, the root of the tree. This is an
0554 * inefficient way to traverse the entire tree; use an iterator instead.
0555 *
0556 * @see #preorderIterator
0557 * @return the node that precedes this node in a pre-order traversal, or
0558 * {@code Optional.empty()} if this node is the first
0559 */
0560 default Optional<T> previousNode() {
0561 Optional<T> node = Optional.empty();
0562
0563 if (parent().isPresent()) {
0564 final Optional<T> prev = previousSibling();
0565 if (prev.isPresent()) {
0566 node = prev.get().childCount() == 0
0567 ? prev
0568 : prev.map(Tree::lastLeaf);
0569 } else {
0570 node = parent();
0571 }
0572 }
0573
0574 return node;
0575 }
0576
0577 /* *************************************************************************
0578 * Sibling query operations
0579 **************************************************************************/
0580
0581 /**
0582 * Test if the given {@code node} is a sibling of {@code this} node.
0583 *
0584 * @param node node to test as sibling of this node
0585 * @return {@code true} if the {@code node} is a sibling of {@code this}
0586 * node
0587 * @throws NullPointerException if the given {@code node} is {@code null}
0588 */
0589 default boolean isSibling(final Tree<?, ?> node) {
0590 return identical(requireNonNull(node)) ||
0591 parent().equals(node.parent());
0592 }
0593
0594 /**
0595 * Return the number of siblings of {@code this} node. A node is its own
0596 * sibling (if it has no parent or no siblings, this method returns
0597 * {@code 1}).
0598 *
0599 * @return the number of siblings of {@code this} node
0600 */
0601 default int siblingCount() {
0602 return parent().map(Tree::childCount).orElse(1);
0603 }
0604
0605 /**
0606 * Return the next sibling of {@code this} node in the parent's children
0607 * array, or {@code null} if {@code this} node has no parent or it is the
0608 * last child of the paren. This method performs a linear search that is
0609 * {@code O(n)} where n is the number of children; to traverse the entire
0610 * array, use the iterator of the parent instead.
0611 *
0612 * @see #childStream()
0613 * @return the sibling of {@code this} node that immediately follows
0614 * {@code this} node
0615 */
0616 default Optional<T> nextSibling() {
0617 return parent().flatMap(p -> p.childAfter(self()));
0618 }
0619
0620 /**
0621 * Return the previous sibling of {@code this} node in the parent's children
0622 * list, or {@code Optional.empty()} if this node has no parent or is the
0623 * parent's first child. This method performs a linear search that is O(n)
0624 * where n is the number of children.
0625 *
0626 * @return the sibling of {@code this} node that immediately precedes this
0627 * node
0628 */
0629 default Optional<T> previousSibling() {
0630 return parent().flatMap(p -> p.childBefore(self()));
0631 }
0632
0633
0634 /* *************************************************************************
0635 * Leaf query operations
0636 **************************************************************************/
0637
0638 /**
0639 * Return {@code true} if {@code this} node has no children.
0640 *
0641 * @return {@code true} if {@code this} node has no children, {@code false}
0642 * otherwise
0643 */
0644 default boolean isLeaf() {
0645 return childCount() == 0;
0646 }
0647
0648 /**
0649 * Return the first leaf that is a descendant of {@code this} node; either
0650 * this node or its first child's first leaf. {@code this} node is returned
0651 * if it is a leaf.
0652 *
0653 * @see #isLeaf
0654 * @see #isDescendant
0655 * @return the first leaf in the subtree rooted at this node
0656 */
0657 default T firstLeaf() {
0658 T leaf = self();
0659 while (!leaf.isLeaf()) {
0660 leaf = leaf.firstChild().orElseThrow(AssertionError::new);
0661 }
0662
0663 return leaf;
0664 }
0665
0666 /**
0667 * Return the last leaf that is a descendant of this node; either
0668 * {@code this} node or its last child's last leaf. Returns {@code this}
0669 * node if it is a leaf.
0670 *
0671 * @see #isLeaf
0672 * @see #isDescendant
0673 * @return the last leaf in this subtree
0674 */
0675 default T lastLeaf() {
0676 T leaf = self();
0677 while (!leaf.isLeaf()) {
0678 leaf = leaf.lastChild().orElseThrow(AssertionError::new);
0679 }
0680
0681 return leaf;
0682 }
0683
0684 /**
0685 * Returns the leaf after {@code this} node or {@code Optional.empty()} if
0686 * this node is the last leaf in the tree.
0687 * <p>
0688 * In order to determine the next node, this method first performs a linear
0689 * search in the parent's child-list in order to find the current node.
0690 * <p>
0691 * That implementation makes the operation suitable for short traversals
0692 * from a known position. But to traverse all the leaves in the tree, you
0693 * should use {@link #depthFirstIterator()} to iterator the nodes in the
0694 * tree and use {@link #isLeaf()} on each node to determine which are leaves.
0695 *
0696 * @see #depthFirstIterator
0697 * @see #isLeaf
0698 * @return return the next leaf past this node
0699 */
0700 default Optional<T> nextLeaf() {
0701 return nextSibling()
0702 .map(Tree::firstLeaf)
0703 .or(() -> parent().flatMap(Tree::nextLeaf));
0704 }
0705
0706 /**
0707 * Return the leaf before {@code this} node or {@code null} if {@code this}
0708 * node is the first leaf in the tree.
0709 * <p>
0710 * In order to determine the previous node, this method first performs a
0711 * linear search in the parent's child-list in order to find the current
0712 * node.
0713 * <p>
0714 * That implementation makes the operation suitable for short traversals
0715 * from a known position. But to traverse all the leaves in the tree, you
0716 * should use {@link #depthFirstIterator()} to iterate the nodes in the tree
0717 * and use {@link #isLeaf()} on each node to determine which are leaves.
0718 *
0719 * @see #depthFirstIterator
0720 * @see #isLeaf
0721 * @return returns the leaf before {@code this} node
0722 */
0723 default Optional<T> previousLeaf() {
0724 return previousSibling()
0725 .map(Tree::lastLeaf)
0726 .or(() -> parent().flatMap(Tree::previousLeaf));
0727 }
0728
0729 /**
0730 * Returns the total number of leaves that are descendants of this node.
0731 * If this node is a leaf, returns {@code 1}. This method is {@code O(n)},
0732 * where n is the number of descendants of {@code this} node.
0733 *
0734 * @see #isLeaf()
0735 * @return the number of leaves beneath this node
0736 */
0737 default int leafCount() {
0738 return (int)leaves().count();
0739 }
0740
0741 /**
0742 * Return a stream of leaves that are descendants of this node.
0743 *
0744 * @since 7.0
0745 *
0746 * @return a stream of leaves that are descendants of this node
0747 */
0748 default Stream<T> leaves() {
0749 return breadthFirstStream().filter(Tree::isLeaf);
0750 }
0751
0752 /* *************************************************************************
0753 * Tree traversing.
0754 **************************************************************************/
0755
0756 /**
0757 * Return an iterator that traverses the subtree rooted at {@code this}
0758 * node in breadth-first order. The first node returned by the iterator is
0759 * {@code this} node.
0760 * <p>
0761 * Modifying the tree by inserting, removing, or moving a node invalidates
0762 * any iterator created before the modification.
0763 *
0764 * @see #depthFirstIterator
0765 * @return an iterator for traversing the tree in breadth-first order
0766 */
0767 default Iterator<T> breadthFirstIterator() {
0768 return new TreeNodeBreadthFirstIterator<>(self());
0769 }
0770
0771 /**
0772 * Return an iterator that traverses the subtree rooted at {@code this}.
0773 * The first node returned by the iterator is {@code this} node.
0774 * <p>
0775 * Modifying the tree by inserting, removing, or moving a node invalidates
0776 * any iterator created before the modification.
0777 *
0778 * @see #breadthFirstIterator
0779 * @return an iterator for traversing the tree in breadth-first order
0780 */
0781 @Override
0782 default Iterator<T> iterator() {
0783 return breadthFirstIterator();
0784 }
0785
0786 /**
0787 * Return a stream that traverses the subtree rooted at {@code this} node in
0788 * breadth-first order. The first node returned by the stream is
0789 * {@code this} node.
0790 *
0791 * @see #depthFirstIterator
0792 * @see #stream()
0793 * @return a stream for traversing the tree in breadth-first order
0794 */
0795 default Stream<T> breadthFirstStream() {
0796 return StreamSupport
0797 .stream(spliteratorUnknownSize(breadthFirstIterator(), 0), false);
0798 }
0799
0800 /**
0801 * Return a stream that traverses the subtree rooted at {@code this} node in
0802 * breadth-first order. The first node returned by the stream is
0803 * {@code this} node.
0804 *
0805 * @see #breadthFirstStream
0806 * @return a stream for traversing the tree in breadth-first order
0807 */
0808 default Stream<T> stream() {
0809 return breadthFirstStream();
0810 }
0811
0812 /**
0813 * Return an iterator that traverses the subtree rooted at {@code this} node
0814 * in pre-order. The first node returned by the iterator is {@code this}
0815 * node.
0816 * <p>
0817 * Modifying the tree by inserting, removing, or moving a node invalidates
0818 * any iterator created before the modification.
0819 *
0820 * @see #postorderIterator
0821 * @return an iterator for traversing the tree in pre-order
0822 */
0823 default Iterator<T> preorderIterator() {
0824 return new TreeNodePreorderIterator<>(self());
0825 }
0826
0827 /**
0828 * Return a stream that traverses the subtree rooted at {@code this} node
0829 * in pre-order. The first node returned by the stream is {@code this} node.
0830 * <p>
0831 * Modifying the tree by inserting, removing, or moving a node invalidates
0832 * any iterator created before the modification.
0833 *
0834 * @see #preorderIterator
0835 * @return a stream for traversing the tree in pre-order
0836 */
0837 default Stream<T> preorderStream() {
0838 return StreamSupport
0839 .stream(spliteratorUnknownSize(preorderIterator(), 0), false);
0840 }
0841
0842 /**
0843 * Return an iterator that traverses the subtree rooted at {@code this}
0844 * node in post-order. The first node returned by the iterator is the
0845 * leftmost leaf. This is the same as a depth-first traversal.
0846 *
0847 * @see #depthFirstIterator
0848 * @see #preorderIterator
0849 * @return an iterator for traversing the tree in post-order
0850 */
0851 default Iterator<T> postorderIterator() {
0852 return new TreeNodePostorderIterator<>(self());
0853 }
0854
0855 /**
0856 * Return a stream that traverses the subtree rooted at {@code this} node in
0857 * post-order. The first node returned by the iterator is the leftmost leaf.
0858 * This is the same as a depth-first traversal.
0859 *
0860 * @see #depthFirstIterator
0861 * @see #preorderIterator
0862 * @return a stream for traversing the tree in post-order
0863 */
0864 default Stream<T> postorderStream() {
0865 return StreamSupport
0866 .stream(spliteratorUnknownSize(postorderIterator(), 0), false);
0867 }
0868
0869 /**
0870 * Return an iterator that traverses the subtree rooted at {@code this} node
0871 * in depth-first order. The first node returned by the iterator is the
0872 * leftmost leaf. This is the same as a postorder traversal.
0873 * <p>
0874 * Modifying the tree by inserting, removing, or moving a node invalidates
0875 * any iterator created before the modification.
0876 *
0877 * @see #breadthFirstIterator
0878 * @see #postorderIterator
0879 * @return an iterator for traversing the tree in depth-first order
0880 */
0881 default Iterator<T> depthFirstIterator() {
0882 return postorderIterator();
0883 }
0884
0885 /**
0886 * Return a stream that traverses the subtree rooted at {@code this} node in
0887 * depth-first. The first node returned by the iterator is the leftmost leaf.
0888 * This is the same as a post-order traversal.
0889 *
0890 * @see #depthFirstIterator
0891 * @see #preorderIterator
0892 * @return a stream for traversing the tree in post-order
0893 */
0894 default Stream<T> depthFirstStream() {
0895 return postorderStream();
0896 }
0897
0898 /**
0899 * Return an iterator that follows the path from {@code ancestor} to
0900 * {@code this} node. The iterator return {@code ancestor} as first element,
0901 * The creation of the iterator is O(m), where m is the number of nodes
0902 * between {@code this} node and the {@code ancestor}, inclusive.
0903 * <p>
0904 * Modifying the tree by inserting, removing, or moving a node invalidates
0905 * any iterator created before the modification.
0906 *
0907 * @see #isAncestor
0908 * @see #isDescendant
0909 * @param ancestor the ancestor node
0910 * @return an iterator for following the path from an ancestor of {@code this}
0911 * node to this one
0912 * @throws IllegalArgumentException if the {@code ancestor} is not an
0913 * ancestor of this node
0914 * @throws NullPointerException if the given {@code ancestor} is {@code null}
0915 */
0916 default Iterator<T> pathFromAncestorIterator(final Tree<?, ?> ancestor) {
0917 return new TreeNodePathIterator<>(ancestor, self());
0918 }
0919
0920 /**
0921 * Return the path of {@code this} child node from the root node. You will
0922 * get {@code this} node, if you call {@link #childAtPath(Path)} on the
0923 * root node of {@code this} node.
0924 * <pre>{@code
0925 * final Tree<?, ?> node = ...;
0926 * final Tree<?, ?> root = node.getRoot();
0927 * final int[] path = node.childPath();
0928 * assert node == root.childAtPath(path);
0929 * }</pre>
0930 *
0931 * @since 4.4
0932 *
0933 * @see #childAtPath(Path)
0934 *
0935 * @return the path of {@code this} child node from the root node.
0936 */
0937 default Path childPath() {
0938 final Iterator<T> it = pathFromAncestorIterator(root());
0939 final int[] path = new int[level()];
0940
0941 T tree = null;
0942 int index = 0;
0943 while (it.hasNext()) {
0944 final T child = it.next();
0945 if (tree != null) {
0946 path[index++] = tree.indexOf(child);
0947 }
0948
0949 tree = child;
0950 }
0951
0952 assert index == path.length;
0953
0954 return new Path(path);
0955 }
0956
0957 /**
0958 * Tests whether {@code this} node is the same as the {@code other} node.
0959 * The default implementation returns the object identity,
0960 * {@code this == other}, of the two objects, but other implementations may
0961 * use different criteria for checking the <i>identity</i>.
0962 *
0963 * @param other the {@code other} node
0964 * @return {@code true} if the {@code other} node is the same as {@code this}
0965 * node.
0966 */
0967 default boolean identical(final Tree<?, ?> other) {
0968 return this == other;
0969 }
0970
0971 /**
0972 * Performs a reduction on the elements of {@code this} tree, using an
0973 * associative reduction function. This can be used for evaluating a given
0974 * expression tree in pre-order.
0975 * <pre>{@code
0976 * final Tree<String, ?> formula = TreeNode.parse("add(sub(6,div(230,10)),mul(5,6))");
0977 * final double result = formula.reduce(new Double[0], (op, args) ->
0978 * switch (op) {
0979 * case "add" -> args[0] + args[1];
0980 * case "sub" -> args[0] - args[1];
0981 * case "mul" -> args[0] * args[1];
0982 * case "div" -> args[0] / args[1];
0983 * default -> Double.parseDouble(op);
0984 * }
0985 * );
0986 * assert result == 13.0;
0987 * }</pre>
0988 *
0989 * @since 7.1
0990 *
0991 * @param neutral the neutral element of the reduction. In most cases this will
0992 * be {@code new U[0]}.
0993 * @param reducer the reduce function
0994 * @param <U> the result type
0995 * @return the result of the reduction, or {@code null} if {@code this} tree
0996 * is empty ({@code isEmpty() == true})
0997 */
0998 default <U> U reduce(
0999 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 6.0
1155 * @since 4.4
1156 */
1157 final class Path implements 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 hashCode() {
1215 return Arrays.hashCode(_path);
1216 }
1217
1218 @Override
1219 public boolean equals(final Object obj) {
1220 return obj == this ||
1221 obj instanceof Path other &&
1222 Arrays.equals(_path, other._path);
1223 }
1224
1225 @Override
1226 public String toString() {
1227 return Arrays.toString(_path);
1228 }
1229
1230 /**
1231 * Create a new path object from the given child indexes.
1232 *
1233 * @param path the child indexes
1234 * @return a new tree path
1235 * @throws IllegalArgumentException if one of the path elements is
1236 * smaller than zero
1237 */
1238 public static Path of(final int... path) {
1239 for (int i = 0; i < path.length; ++i) {
1240 if (path[i] < 0) {
1241 throw new IllegalArgumentException(format(
1242 "Path element at position %d is smaller than zero: %d",
1243 i, path[i]
1244 ));
1245 }
1246 }
1247
1248 return new Path(path.clone());
1249 }
1250
1251
1252 /* *********************************************************************
1253 * Java object serialization
1254 * ********************************************************************/
1255
1256 @Serial
1257 private Object writeReplace() {
1258 return new SerialProxy(SerialProxy.TREE_PATH, this);
1259 }
1260
1261 @Serial
1262 private void readObject(final ObjectInputStream stream)
1263 throws InvalidObjectException
1264 {
1265 throw new InvalidObjectException("Serialization proxy required.");
1266 }
1267
1268
1269 void write(final DataOutput out) throws IOException {
1270 writeIntArray(_path, out);
1271 }
1272
1273 static Object read(final DataInput in) throws IOException {
1274 return Path.of(readIntArray(in));
1275 }
1276
1277 }
1278
1279 }
|