feat!: v4.0 breaking API cleanup + explicitApi

BREAKING changes to the core:
- treeIterator is now a read-only `val`; added `iterator(order)` and use `asSequence(order)`.
- removeChild() only removes a direct child of the receiver; added `detach()` to unhook a node.
- addChild() rejects re-parenting and cycles (throws TreeNodeException); detach() first to move.
- clear() no longer nulls the receiver's own parent; only removes descendants.
- path() returns List<TreeNode<T>>? (null) instead of throwing.

Also:
- Enable strict explicitApi() across core + both modules; add explicit `public` modifiers.
- Update tests for the new contracts + add TreeNodeV4Test; refresh .api baselines.
- README + CHANGELOG (with migration notes); bump version to 4.0.0.

47 JVM tests green.
This commit is contained in:
2026-06-07 18:47:40 +02:00
parent c9bbea59b0
commit 69d19f89e3
22 changed files with 262 additions and 97 deletions

View File

@@ -20,7 +20,7 @@ import com.github.adriankuta.datastructure.tree.TreeNode
* Output: 1 2 3 4 5 6 7 8 9 10 11 12 13
* ```
*/
class LevelOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
public class LevelOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
private val stack = ArrayDeque<TreeNode<T>>()
@@ -28,9 +28,9 @@ class LevelOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
stack.addLast(root)
}
override fun hasNext(): Boolean = stack.isNotEmpty()
public override fun hasNext(): Boolean = stack.isNotEmpty()
override fun next(): TreeNode<T> {
public override fun next(): TreeNode<T> {
val node = stack.removeFirst()
node.children
.forEach { stack.addLast(it) }

View File

@@ -20,7 +20,7 @@ import com.github.adriankuta.datastructure.tree.TreeNode
* Output: 10 5 11 12 13 6 2 3 7 8 9 4 1
* ```
*/
class PostOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
public class PostOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
private val result = ArrayDeque<TreeNode<T>>()
@@ -37,7 +37,7 @@ class PostOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
}
}
override fun hasNext(): Boolean = result.isNotEmpty()
public override fun hasNext(): Boolean = result.isNotEmpty()
override fun next(): TreeNode<T> = result.removeFirst()
public override fun next(): TreeNode<T> = result.removeFirst()
}

View File

@@ -20,7 +20,7 @@ import com.github.adriankuta.datastructure.tree.TreeNode
* Output: 1 2 5 10 6 11 12 13 3 4 7 8 9
* ```
*/
class PreOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
public class PreOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
private val stack = ArrayDeque<TreeNode<T>>()
@@ -28,9 +28,9 @@ class PreOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
stack.addLast(root)
}
override fun hasNext(): Boolean = stack.isNotEmpty()
public override fun hasNext(): Boolean = stack.isNotEmpty()
override fun next(): TreeNode<T> {
public override fun next(): TreeNode<T> {
val node = stack.removeLast()
node.children
.asReversed()

View File

@@ -5,7 +5,7 @@ package com.github.adriankuta.datastructure.tree.iterators
* @see PostOrder
* @see LevelOrder
*/
enum class TreeNodeIterators {
public enum class TreeNodeIterators {
/**
* Tree is iterated by using `Pre-order Traversal Algorithm"
* The pre-order traversal is a topologically sorted one,