feat: stack-safe traversal + lazy Sequence + navigation/functional extensions

Core additive work for v3.4 (non-breaking):

- Rewrite nodeCount(), height(), clear() and the post-order iterator iteratively
  so deep/degenerate trees no longer throw StackOverflowError (verified to 50k deep).
- Add lazy Sequence traversal: asSequence(order), pre/post/levelOrderSequence().
- Add navigation extensions: isLeaf, degree, root(), ancestors(), siblings(),
  leaves(), descendants().
- Add functional extensions: findNode, filterNodes, anyNode, allNodes, countNodes,
  foldNodes, mapValues, deepCopy, structurallyEquals (all stack-safe).
- Add tests for stack-safety, the new APIs, and previously-uncovered
  height/depth/nodeCount/path (incl. exception paths). 40 tests green on JVM.
This commit is contained in:
2026-06-06 13:35:39 +02:00
parent 6de95f7976
commit c45c5b7afa
10 changed files with 473 additions and 29 deletions

View File

@@ -0,0 +1,31 @@
package com.github.adriankuta.datastructure.tree
import com.github.adriankuta.datastructure.tree.iterators.LevelOrderTreeIterator
import com.github.adriankuta.datastructure.tree.iterators.PostOrderTreeIterator
import com.github.adriankuta.datastructure.tree.iterators.PreOrderTreeIterator
import com.github.adriankuta.datastructure.tree.iterators.TreeNodeIterators
/**
* Lazily traverses this subtree in the given [order] as a [Sequence], without forcing the whole
* traversal up front. Pairs with the Kotlin stdlib, e.g.
* `root.asSequence().map { it.value }.firstOrNull { it == target }`.
*/
fun <T> TreeNode<T>.asSequence(
order: TreeNodeIterators = TreeNodeIterators.PreOrder,
): Sequence<TreeNode<T>> {
val self = this
return when (order) {
TreeNodeIterators.PreOrder -> Sequence { PreOrderTreeIterator(self) }
TreeNodeIterators.PostOrder -> Sequence { PostOrderTreeIterator(self) }
TreeNodeIterators.LevelOrder -> Sequence { LevelOrderTreeIterator(self) }
}
}
/** Lazy pre-order traversal as a [Sequence]. */
fun <T> TreeNode<T>.preOrderSequence(): Sequence<TreeNode<T>> = asSequence(TreeNodeIterators.PreOrder)
/** Lazy post-order traversal as a [Sequence]. */
fun <T> TreeNode<T>.postOrderSequence(): Sequence<TreeNode<T>> = asSequence(TreeNodeIterators.PostOrder)
/** Lazy level-order (breadth-first) traversal as a [Sequence]. */
fun <T> TreeNode<T>.levelOrderSequence(): Sequence<TreeNode<T>> = asSequence(TreeNodeIterators.LevelOrder)