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