5: Implement post-order traversal algorithm (#16)

This commit is contained in:
2022-12-16 18:57:34 +01:00
committed by GitHub
parent 8a2710339a
commit b69e838a8a
6 changed files with 118 additions and 8 deletions

View File

@@ -1,5 +1,9 @@
package com.github.adriankuta
import com.github.adriankuta.iterators.PostOrderTreeIterator
import com.github.adriankuta.iterators.PreOrderTreeIterator
import com.github.adriankuta.iterators.TreeNodeIterators
import com.github.adriankuta.iterators.TreeNodeIterators.*
import kotlin.jvm.JvmSynthetic
open class TreeNode<T>(val value: T) : Iterable<TreeNode<T>>, ChildDeclarationInterface<T> {
@@ -18,6 +22,8 @@ open class TreeNode<T>(val value: T) : Iterable<TreeNode<T>>, ChildDeclarationIn
val children: List<TreeNode<T>>
get() = _children
var defaultIterator: TreeNodeIterators = PreOrder
/**
* Add new child to current node or root.
*
@@ -139,5 +145,8 @@ open class TreeNode<T>(val value: T) : Iterable<TreeNode<T>>, ChildDeclarationIn
* Output: 1 2 5 10 6 11 12 13 3 4 7 8 9
* ```
*/
override fun iterator(): Iterator<TreeNode<T>> = PreOrderTreeIterator(this)
override fun iterator(): Iterator<TreeNode<T>> = when (defaultIterator) {
PreOrder -> PreOrderTreeIterator(this)
PostOrder -> PostOrderTreeIterator(this)
}
}

View File

@@ -1,5 +1,6 @@
package com.github.adriankuta
import com.github.adriankuta.iterators.TreeNodeIterators
import kotlin.jvm.JvmSynthetic
typealias ChildDeclaration<T> = ChildDeclarationInterface<T>.() -> Unit
@@ -13,8 +14,13 @@ typealias ChildDeclaration<T> = ChildDeclarationInterface<T>.() -> Unit
* @see [ChildDeclarationInterface.child]
*/
@JvmSynthetic
inline fun<reified T> tree(root: T, childDeclaration: ChildDeclaration<T>): TreeNode<T> {
inline fun <reified T> tree(
root: T,
defaultIterator: TreeNodeIterators = TreeNodeIterators.PreOrder,
childDeclaration: ChildDeclaration<T>
): TreeNode<T> {
val treeNode = TreeNode(root)
treeNode.defaultIterator = defaultIterator
treeNode.childDeclaration()
return treeNode
}

View File

@@ -0,0 +1,50 @@
package com.github.adriankuta.iterators
import com.github.adriankuta.TreeNode
/**
* Tree is iterated by using `Post-order Traversal Algorithm"
* 1. Check if the current node is empty or null.
* 2. Display the data part of the root (or current node).
* 3. Traverse the left subtree by recursively calling the pre-order function.
* 4. Traverse the right subtree by recursively calling the pre-order function.
* ```
* E.g.
* 1
* / | \
* / | \
* 2 3 4
* / \ / | \
* 5 6 7 8 9
* / / | \
* 10 11 12 13
*
* Output: 1 2 5 10 6 11 12 13 3 4 7 8 9
* ```
*/
class PostOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
private val stack = ArrayDeque<TreeNode<T>>()
init {
stack.addAll(getChildrenStack(root))
}
override fun hasNext(): Boolean = stack.isNotEmpty()
override fun next(): TreeNode<T> {
return stack.removeFirst()
}
private fun getChildrenStack(node: TreeNode<T>): ArrayDeque<TreeNode<T>> {
val stack = ArrayDeque<TreeNode<T>>()
if(node.children.isEmpty()) {
return ArrayDeque(listOf(node))
}
node.children.forEach {
stack.addAll(getChildrenStack(it))
}
stack.addLast(node)
return stack
}
}

View File

@@ -1,4 +1,6 @@
package com.github.adriankuta
package com.github.adriankuta.iterators
import com.github.adriankuta.TreeNode
/**
* Tree is iterated by using `Pre-order Traversal Algorithm"
@@ -31,10 +33,12 @@ class PreOrderTreeIterator<T>(root: TreeNode<T>) : Iterator<TreeNode<T>> {
override fun hasNext(): Boolean = stack.isNotEmpty()
override fun next(): TreeNode<T> {
println(stack)
val node = stack.removeLast()
node.children
.asReversed()
.forEach { stack.addLast(it) }
println(stack)
return node
}
}

View File

@@ -0,0 +1,5 @@
package com.github.adriankuta.iterators
enum class TreeNodeIterators {
PreOrder, PostOrder
}