From 4aacbc9dbcebb8c2552189225bf014e0247a1aa0 Mon Sep 17 00:00:00 2001 From: Adrian Kuta Date: Wed, 22 Feb 2023 14:29:22 +0100 Subject: [PATCH] 21: Added `path` function to `TreeNode` (#22) Path refers to the sequence of nodes along the edges of a tree. --- build.gradle.kts | 6 ++- .../datastructure/tree/TreeNode.kt | 44 ++++++++++++++++++- .../datastructure/tree/TreeNodeExt.kt | 1 + .../tree/exceptions/TreeNodeException.kt | 6 +++ .../{ => iterators}/LevelOrderTreeIterator.kt | 4 +- .../{ => iterators}/PostOrderTreeIterator.kt | 4 +- .../{ => iterators}/PreOrderTreeIterator.kt | 4 +- .../tree/{ => iterators}/TreeNodeIterators.kt | 2 +- .../datastructure.tree/TreeNodeTest.kt | 1 + src/jvmMain/kotlin/Example.ws.kts | 14 ++++++ 10 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/exceptions/TreeNodeException.kt rename src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/{ => iterators}/LevelOrderTreeIterator.kt (88%) rename src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/{ => iterators}/PostOrderTreeIterator.kt (90%) rename src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/{ => iterators}/PreOrderTreeIterator.kt (88%) rename src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/{ => iterators}/TreeNodeIterators.kt (96%) create mode 100644 src/jvmMain/kotlin/Example.ws.kts diff --git a/build.gradle.kts b/build.gradle.kts index e575cbf..e4e2b17 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -135,7 +135,11 @@ kotlin { implementation(kotlin("test")) } } - val jvmMain by getting + val jvmMain by getting { + dependencies { + implementation(kotlin("script-runtime")) + } + } val jvmTest by getting val jsMain by getting val jsTest by getting diff --git a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNode.kt b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNode.kt index 3be6297..5728f00 100644 --- a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNode.kt +++ b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNode.kt @@ -1,11 +1,17 @@ package com.github.adriankuta.datastructure.tree -import com.github.adriankuta.datastructure.tree.TreeNodeIterators.* +import com.github.adriankuta.datastructure.tree.exceptions.TreeNodeException +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 +import com.github.adriankuta.datastructure.tree.iterators.TreeNodeIterators.* import kotlin.jvm.JvmSynthetic open class TreeNode(val value: T) : Iterable>, ChildDeclarationInterface { private var _parent: TreeNode? = null + /** * The converse notion of a child, an immediate ancestor. */ @@ -13,12 +19,20 @@ open class TreeNode(val value: T) : Iterable>, ChildDeclarationIn get() = _parent private val _children = mutableListOf>() + /** * A group of nodes with the same parent. */ val children: List> get() = _children + /** + * Checks whether the current tree node is the root of the tree + * @return `true` if the current tree node is root of the tree, `false` otherwise. + */ + val isRoot: Boolean + get() = _parent == null + /** * Choose one of available iterators from [TreeNodeIterators] */ @@ -37,7 +51,8 @@ open class TreeNode(val value: T) : Iterable>, ChildDeclarationIn @JvmSynthetic override fun child(value: T, childDeclaration: ChildDeclaration?): TreeNode { val newChild = TreeNode(value) - if(childDeclaration != null) + newChild._parent = this + if (childDeclaration != null) newChild.childDeclaration() _children.add(newChild) return newChild @@ -91,6 +106,31 @@ open class TreeNode(val value: T) : Iterable>, ChildDeclarationIn return depth } + /** + * Returns the collection of nodes, which connect the current node + * with its descendants + * + * @param descendant the bottom child node for which the path is calculated + * @return collection of nodes, which connect the current node with its descendants + * @throws TreeNodeException exception that may be thrown in case if the + * current node does not have such descendant or if the + * specified tree node is root + */ + @Throws(TreeNodeException::class) + fun path(descendant: TreeNode): List> { + + val path = mutableListOf>() + var node = descendant + path.add(node) + while (!node.isRoot) { + node = node.parent!! + path.add(node) + if (node == this) + return path + } + throw TreeNodeException("The specified tree node $descendant is not the descendant of tree node $this") + } + /** * Remove all children from root and every node in tree. */ diff --git a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNodeExt.kt b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNodeExt.kt index 77a4419..e8e02b6 100644 --- a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNodeExt.kt +++ b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNodeExt.kt @@ -1,5 +1,6 @@ package com.github.adriankuta.datastructure.tree +import com.github.adriankuta.datastructure.tree.iterators.TreeNodeIterators import kotlin.jvm.JvmSynthetic typealias ChildDeclaration = ChildDeclarationInterface.() -> Unit diff --git a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/exceptions/TreeNodeException.kt b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/exceptions/TreeNodeException.kt new file mode 100644 index 0000000..a4d4cc3 --- /dev/null +++ b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/exceptions/TreeNodeException.kt @@ -0,0 +1,6 @@ +package com.github.adriankuta.datastructure.tree.exceptions + +import kotlin.jvm.JvmOverloads + +class TreeNodeException @JvmOverloads constructor(message: String? = null, cause: Throwable? = null) : + RuntimeException(message, cause) \ No newline at end of file diff --git a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/LevelOrderTreeIterator.kt b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/LevelOrderTreeIterator.kt similarity index 88% rename from src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/LevelOrderTreeIterator.kt rename to src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/LevelOrderTreeIterator.kt index 87c959d..db852c4 100644 --- a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/LevelOrderTreeIterator.kt +++ b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/LevelOrderTreeIterator.kt @@ -1,4 +1,6 @@ -package com.github.adriankuta.datastructure.tree +package com.github.adriankuta.datastructure.tree.iterators + +import com.github.adriankuta.datastructure.tree.TreeNode /** * Tree is iterated by using `Level-order Traversal Algorithm" diff --git a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/PostOrderTreeIterator.kt b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/PostOrderTreeIterator.kt similarity index 90% rename from src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/PostOrderTreeIterator.kt rename to src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/PostOrderTreeIterator.kt index d1c4b11..6eb6bbf 100644 --- a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/PostOrderTreeIterator.kt +++ b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/PostOrderTreeIterator.kt @@ -1,4 +1,6 @@ -package com.github.adriankuta.datastructure.tree +package com.github.adriankuta.datastructure.tree.iterators + +import com.github.adriankuta.datastructure.tree.TreeNode /** * Tree is iterated by using `Post-order Traversal Algorithm" diff --git a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/PreOrderTreeIterator.kt b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/PreOrderTreeIterator.kt similarity index 88% rename from src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/PreOrderTreeIterator.kt rename to src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/PreOrderTreeIterator.kt index 79e73d2..5975a88 100644 --- a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/PreOrderTreeIterator.kt +++ b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/PreOrderTreeIterator.kt @@ -1,4 +1,6 @@ -package com.github.adriankuta.datastructure.tree +package com.github.adriankuta.datastructure.tree.iterators + +import com.github.adriankuta.datastructure.tree.TreeNode /** * Tree is iterated by using `Pre-order Traversal Algorithm" diff --git a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNodeIterators.kt b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/TreeNodeIterators.kt similarity index 96% rename from src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNodeIterators.kt rename to src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/TreeNodeIterators.kt index f333125..b66b2ce 100644 --- a/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/TreeNodeIterators.kt +++ b/src/commonMain/kotlin/com.github.adriankuta/datastructure/tree/iterators/TreeNodeIterators.kt @@ -1,4 +1,4 @@ -package com.github.adriankuta.datastructure.tree +package com.github.adriankuta.datastructure.tree.iterators /** * @see PreOrder diff --git a/src/commonTest/kotlin/com.github.adriankuta/datastructure.tree/TreeNodeTest.kt b/src/commonTest/kotlin/com.github.adriankuta/datastructure.tree/TreeNodeTest.kt index a3ca1f5..7ac21f6 100644 --- a/src/commonTest/kotlin/com.github.adriankuta/datastructure.tree/TreeNodeTest.kt +++ b/src/commonTest/kotlin/com.github.adriankuta/datastructure.tree/TreeNodeTest.kt @@ -1,5 +1,6 @@ package com.github.adriankuta.datastructure.tree +import com.github.adriankuta.datastructure.tree.iterators.TreeNodeIterators import kotlin.test.Test import kotlin.test.assertContentEquals import kotlin.test.assertEquals diff --git a/src/jvmMain/kotlin/Example.ws.kts b/src/jvmMain/kotlin/Example.ws.kts new file mode 100644 index 0000000..162936a --- /dev/null +++ b/src/jvmMain/kotlin/Example.ws.kts @@ -0,0 +1,14 @@ +import com.github.adriankuta.datastructure.tree.tree + +val root = + tree("World") { + child("North America") { + child("USA") + } + child("Europe") { + child("Poland") + child("Germany") + } + } + +print(root.prettyString()) \ No newline at end of file